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

    Competitierekending

    Given a time or distance performed at a competition event, calculate
    the number of points. And the other way around.

    Formulas are taken from 'Formules en Constanten' [1], January 2004
    version, part of Wedstrijdreglement Atletiekunie.

    Version 1.0, 2010-01-28

    Copyright 2010, Martijn Vermaat <martijn@vermaat.name>
                    Sander van der Kruyssen <sandiaan@gmail.com>

    http://svn.vermaat.name/competitie-rekending

    Licensed under the MIT license [2], see the LICENSE file

    [1] http://www.atletiekunie.nl/upload/File/Dutch_Athletes/Formules%20en%20constanten%20(20-11-03).doc
    [2] http://en.wikipedia.org/wiki/Mit_license

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

$(document).ready(function() {

    // TODO: image preloading, comments

    var TO_POINTS = 0;
    var TO_PERFORMANCE = 1;
    var direction = TO_POINTS;

    var loc = window.location;
    var url = loc.href.replace(/^([^#?]*\??[^#]*)#?(.*)/, '$1');
    var state = loc.href.replace(/^([^#?]*\??[^#]*)#?(.*)/, '$2');

    var bookmarks = [];

    var calculate = function() {

        if (direction == TO_POINTS) {
            var points = calculator.points($('#events').val(),
                                           $('#male').is(':checked'),
                                           $('#performance').val());
            if (!isNaN(points))
                $('#points').val(points.toString());
        } else {
            $('#performance').val(
                calculator.performance($('#events').val(),
                                       $('#male').is(':checked'),
                                       $('#points').val()));
        }

        updateBookmark();

    };

    var toPoints = function() {
        direction = TO_POINTS;
        calculate();
    };

    var toPerformance = function() {
        direction = TO_PERFORMANCE;
        calculate();
    };

    var updateBookmark = function() {

        $('#bookmark').unbind('click');

        if (isNaN(parseInt($('#events').val()))
            || $('#points').val() == ''
            || $('#performance').val() == '') {

            $('#bookmark').bind('click', function() {
                return false;
            }).addClass('disabled');

        } else {

            $('#bookmark').click(function() {
                bookmark($('#events').val(),
                         $('#male').is(':checked'),
                         $('#performance').val(),
                         $('#points').val());
                return false;
            }).removeClass('disabled');

        }

    };

    var bookmark = function(event, sex, performance, points) {

        var hash = Math.floor(Math.random() * 100000000);

        bookmarks.push({'hash' : hash,
                        'e'    : event,
                        's'    : sex,
                        'p'    : performance,
                        'q'    : points});

        var r = $('Verwijder dit resultaat');
        r.attr('title', r.text()).click(function() {
            bookmarks = $.grep(bookmarks, function(b, i) {
                return b.hash != hash;
            });
            $(this).parent().remove();
            updateLocation();
            return false;
        });

        var s = $('#events option[value=' + event + ']').text();
        s += ' (' + (sex ? 'm' : 'v') + '): ';
        s += performance + ', ' + points;

        $('#bookmarks').append(
            $('
').text(s).prepend(r)
        );

        updateLocation();

    };

    var updateLocation = function() {

        try {
            var s = JSON.stringify($.map(bookmarks, function(b) {
                // Don't include hash to keep state small
                return {
                    'e' : b.e,
                    's' : b.s,
                    'p' : b.p,
                    'q' : b.q
                };
            }));
            loc.href = url + '#' + encodeURIComponent(s);
            $('#mail').attr(
                'href',
                'mailto:?subject=Competitieresultaten&body=De resultaten: '
                    + loc.href
            ).show();
        } catch (e) {
            $('#mail').hide();
        }

        if (bookmarks.length > 0) {
            $('#bookmarks-title').show();
        } else {
            $('#bookmarks-title').hide();
        }

    };

    var loadBookmarks = function() {

        try {
            var p = JSON.parse(decodeURIComponent(state));
            for (i = 0; i < p.length; i++) {
                bookmark(p[i].e, p[i].s, p[i].p, p[i].q);
            }
        } catch (e) {}

    };

    var ignoreNav = function(callback) {
        // Call callback if key was not <tab> or <shift>
        return function(e) {
            if (e.keyCode != 9 && e.keyCode != 0)
                callback(e);
        };
    };

    var bookmarkShortcut = function(e) {
        // Key 'b'
        if (e.which == 98 || e.which == 66) {
            e.preventDefault();
            e.stopPropagation();
            if (!$('#bookmark').hasClass('disabled'))
                $('#bookmark').click();
        }
    };

    var events = calculator.events();
    for (i = 0; i < events.length; i++)
        $('#events').append($('<option>').val(i).text(events[i]));

    $('#events').bind('change keyup', calculate);

    $('#male, #female').click(calculate);

    $('#performance').keyup(ignoreNav(toPoints));
    $('#points').keyup(ignoreNav(toPerformance));

    $(document).keypress(bookmarkShortcut);

    updateLocation();
    updateBookmark();
    loadBookmarks();

});
<commit_msg>Encoding of non-ascii characters in state string.<commit_after>/***********************************************************************

    Competitierekending

    Given a time or distance performed at a competition event, calculate
    the number of points. And the other way around.

    Formulas are taken from 'Formules en Constanten' [1], January 2004
    version, part of Wedstrijdreglement Atletiekunie.

    Version 1.0, 2010-01-28

    Copyright 2010, Martijn Vermaat <martijn@vermaat.name>
                    Sander van der Kruyssen <sandiaan@gmail.com>

    http://svn.vermaat.name/competitie-rekending

    Licensed under the MIT license [2], see the LICENSE file

    [1] http://www.atletiekunie.nl/upload/File/Dutch_Athletes/Formules%20en%20constanten%20(20-11-03).doc
    [2] http://en.wikipedia.org/wiki/Mit_license

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

$(document).ready(function() {

    // TODO: image preloading, comments

    var TO_POINTS = 0;
    var TO_PERFORMANCE = 1;
    var direction = TO_POINTS;

    var loc = window.location;
    var url = loc.href.replace(/^([^#?]*\??[^#]*)#?(.*)/, '$1');
    var state = loc.href.replace(/^([^#?]*\??[^#]*)#?(.*)/, '$2');

    var bookmarks = [];

    var calculate = function() {

        if (direction == TO_POINTS) {
            var points = calculator.points($('#events').val(),
                                           $('#male').is(':checked'),
                                           $('#performance').val());
            if (!isNaN(points))
                $('#points').val(points.toString());
        } else {
            $('#performance').val(
                calculator.performance($('#events').val(),
                                       $('#male').is(':checked'),
                                       $('#points').val()));
        }

        updateBookmark();

    };

    var toPoints = function() {
        direction = TO_POINTS;
        calculate();
    };

    var toPerformance = function() {
        direction = TO_PERFORMANCE;
        calculate();
    };

    var updateBookmark = function() {

        $('#bookmark').unbind('click');

        if (isNaN(parseInt($('#events').val()))
            || $('#points').val() == ''
            || $('#performance').val() == '') {

            $('#bookmark').bind('click', function() {
                return false;
            }).addClass('disabled');

        } else {

            $('#bookmark').click(function() {
                bookmark($('#events').val(),
                         $('#male').is(':checked'),
                         $('#performance').val(),
                         $('#points').val());
                return false;
            }).removeClass('disabled');

        }

    };

    var bookmark = function(event, sex, performance, points) {

        var hash = Math.floor(Math.random() * 100000000);

        bookmarks.push({'hash' : hash,
                        'e'    : event,
                        's'    : sex,
                        'p'    : performance,
                        'q'    : points});

        var r = $('Verwijder dit resultaat');
        r.attr('title', r.text()).click(function() {
            bookmarks = $.grep(bookmarks, function(b, i) {
                return b.hash != hash;
            });
            $(this).parent().remove();
            updateLocation();
            return false;
        });

        var s = $('#events option[value=' + event + ']').text();
        s += ' (' + (sex ? 'm' : 'v') + '): ';
        s += performance + ', ' + points;

        $('#bookmarks').append(
            $('
').text(s).prepend(r)
        );

        updateLocation();

    };

    var encodeState = function(s) {

        var r = JSON.stringify($.map(s, function(b) {
            // Don't include hash to keep state small
            return {
                'e' : b.e,
                's' : b.s,
                'p' : b.p,
                'q' : b.q
            };
        }));

        var map = [];
        map['"'] = 'A';
        map[':'] = 'B';
        map[','] = 'C';
        map['['] = 'D';
        map[']'] = 'E';
        map['{'] = 'F';
        map['}'] = 'G';

        return encodeURIComponent(
            r.replace(/[":,\[\]{}]/g,
                      function(c) { return map[c]; })
        );

    };

    var decodeState = function(s) {

        var r = decodeURIComponent(s);

        var map = [];
        map['A'] = '"';
        map['B'] = ':';
        map['C'] = ',';
        map['D'] = '[';
        map['E'] = ']';
        map['F'] = '{';
        map['G'] = '}';

        return JSON.parse(
            r.replace(/[ABCDEFG]/g,
                      function(c) { return map[c]; })
        );

    };

    var updateLocation = function() {

        try {
            loc.href = url + '#' + encodeState(bookmarks);
            $('#mail').attr(
                'href',
                'mailto:?subject=Competitieresultaten&body=De resultaten: '
                    + loc.href
            ).show();
        } catch (e) {
            $('#mail').hide();
        }

        if (bookmarks.length > 0) {
            $('#bookmarks-title').show();
        } else {
            $('#bookmarks-title').hide();
        }

    };

    var loadBookmarks = function(s) {

        try {
            var p = decodeState(s);
            for (i = 0; i < p.length; i++) {
                bookmark(p[i].e, p[i].s, p[i].p, p[i].q);
            }
        } catch (e) {}

    };

    var ignoreNav = function(callback) {
        // Call callback if key was not <tab> or <shift>
        return function(e) {
            if (e.keyCode != 9 && e.keyCode != 0)
                callback(e);
        };
    };

    var bookmarkShortcut = function(e) {
        // Key 'b'
        if (e.which == 98 || e.which == 66) {
            e.preventDefault();
            e.stopPropagation();
            if (!$('#bookmark').hasClass('disabled'))
                $('#bookmark').click();
        }
    };

    var events = calculator.events();
    for (i = 0; i < events.length; i++)
        $('#events').append($('<option>').val(i).text(events[i]));

    $('#events').bind('change keyup', calculate);

    $('#male, #female').click(calculate);

    $('#performance').keyup(ignoreNav(toPoints));
    $('#points').keyup(ignoreNav(toPerformance));

    $(document).keypress(bookmarkShortcut);

    updateLocation();
    updateBookmark();
    loadBookmarks(state);

});
<|endoftext|>


<commit_before>/**
 * jQuery yiiactiveform plugin file.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @link http://www.yiiframework.com/
 * @copyright Copyright © 2008-2010 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 * @version $Id$
 * @since 1.1.1
 */

;(function($) {
	/**
	 * yiiactiveform set function.
	 * @param map settings for the active form plugin. Please see {@link CActiveForm::options} for availablel options.
	 */
	$.fn.yiiactiveform = function(options) {
		return this.each(function() {
			var settings = $.extend({}, $.fn.yiiactiveform.defaults, options || {});
			var $form = $(this);
			var id = $form.attr('id');
			if(settings.validationUrl == undefined)
				settings.validationUrl = $form.attr('action');
			$.each(settings.attributes, function(i,attribute){
				settings.attributes[i] = $.extend({
					validationDelay : settings.validationDelay,
					validateOnChange : settings.validateOnChange,
					validateOnType : settings.validateOnType,
					hideErrorMessage : settings.hideErrorMessage,
					inputContainer : settings.inputContainer,
					errorCssClass : settings.errorCssClass,
					successCssClass : settings.successCssClass,
					beforeValidateAttribute : settings.beforeValidateAttribute,
					afterValidateAttribute : settings.afterValidateAttribute,
					validatingCssClass : settings.validatingCssClass
				}, attribute);
				settings.attributes[i].value = $('#'+attribute.inputID).val();
			});
			$(this).data('settings', settings);

			var validate = function(attribute, forceValidate) {
				if (forceValidate)
					attribute.status = 2;
				$.each(settings.attributes, function(){
					if (this.value != $('#'+this.inputID).val()) {
						this.status = 2;
						forceValidate = true;
					}
				});
				if (!forceValidate)
					return;

				if(settings.timer!=undefined) {
					clearTimeout(settings.timer);
				}

				settings.timer = setTimeout(function(){
					if(attribute.beforeValidateAttribute==undefined || attribute.beforeValidateAttribute($form, attribute)) {
						$.each(settings.attributes, function(){
							if (this.status == 2) {
								this.status = 3;
								getInputContainer(this).addClass(this.validatingCssClass);
							}
						});
						$.fn.yiiactiveform.validate($form, function(data) {
							var hasError=false;
							$.each(settings.attributes, function(){
								if (this.status > 0) {
									hasError = $.fn.yiiactiveform.updateInput(this, data) || hasError;
								}
							});
							if(attribute.afterValidateAttribute!=undefined) {
								attribute.afterValidateAttribute($form,attribute,data,hasError);
							}
						});
					};
				}, attribute.validationDelay);
			};

			$.each(settings.attributes, function(i, attribute) {
				if (attribute.validateOnChange) {
					$('#'+attribute.inputID).change(function(){
						validate(attribute,false);
					}).blur(function(){
						if(attribute.status!=2 && attribute.status!=3)
							validate(attribute, !attribute.status);
					});
				}
				if (attribute.validateOnType) {
					$('#'+attribute.inputID).keyup(function(){
						if (attribute.value != $('#'+attribute.inputID).val())
							validate(attribute, false);
					});
				}
			});

			if (settings.validateOnSubmit) {
				$form.find(':submit').live('mouseup keyup',function(){
					$form.data('submitObject',$(this));
				});
				var validated = false;
				$form.submit(function(){
					if (validated)
						return true;
					if(settings.beforeValidate==undefined || settings.beforeValidate($form)) {
						$.fn.yiiactiveform.validate($form, function(data){
							var hasError = false;
							$.each(settings.attributes, function(i, attribute){
								hasError = $.fn.yiiactiveform.updateInput(attribute, data) || hasError;
							});
							$.fn.yiiactiveform.updateSummary($form, data);
							if(settings.afterValidate==undefined || settings.afterValidate($form, data, hasError)) {
								if(!hasError) {
									validated = true;
									var $button = $form.data('submitObject') || $form.find(':submit:first');
									// TODO: if the submission is caused by "change" event, it will not work
									if ($button.length)
										$button.click();
									else  // no submit button in the form
										$form.submit();
								}
							}
						});
					}
					return false;
				});
			}
		});
	};

	/**
	 * Returns the container element of the specified attribute.
	 * @param object the configuration for a particular attribute.
	 * @return jquery the jquery representation of the container
	 */
	$.fn.yiiactiveform.getInputContainer = function(attribute) {
		if(attribute.inputContainer == undefined)
			return $('#'+attribute.inputID).closest('div');
		else
			return $(attribute.inputContainer).filter(':has("#'+attribute.inputID+'")');
	};

	/**
	 * updates the error message and the input container for a particular attribute.
	 * @param object the configuration for a particular attribute.
	 * @param array the json data obtained from the ajax validation request
	 * @return boolean whether there is a validation error for the specified attribute
	 */
	$.fn.yiiactiveform.updateInput = function(attribute, messages) {
		attribute.status = 1;
		var hasError = messages!=null && $.isArray(messages[attribute.inputID]) && messages[attribute.inputID].length>0;
		var $error = $('#'+attribute.errorID);
		var $container = $.fn.yiiactiveform.getInputContainer(attribute);
		$container.removeClass(attribute.validatingCssClass)
			.removeClass(attribute.errorCssClass)
			.removeClass(attribute.successCssClass);

		if(hasError) {
			$error.html(messages[attribute.inputID][0]);
			$container.addClass(attribute.errorCssClass);
		}
		else {
			$container.addClass(attribute.successCssClass);
		}
		if(!attribute.hideErrorMessage)
			$error.toggle(hasError);

		attribute.value = $('#'+attribute.inputID).val();

		return hasError;
	};

	/**
	 * updates the error summary, if any.
	 * @param jquery the jquery representation of the form
	 * @param array the json data obtained from the ajax validation request
	 */
	$.fn.yiiactiveform.updateSummary = function(form, messages) {
		var settings = $(form).data('settings');
		if (settings.summaryID == undefined)
			return;
		var content = '';
		$.each(settings.attributes, function(i, attribute){
			if(messages && $.isArray(messages[attribute.inputID])) {
				$.each(messages[attribute.inputID],function(j,message){
					content = content + '
' + message + '
';
				});
			}
		});
		$('#'+settings.summaryID+' ul').html(content);
		$('#'+settings.summaryID).toggle(content!='');
	};

	/**
	 * Performs the ajax validation request.
	 * This method is invoked internally to trigger the ajax validation.
	 * @param jquery the jquery representation of the form
	 * @param function the function to be invoked if the ajax request succeeds
	 * @param function the function to be invoked if the ajax request fails
	 */
	$.fn.yiiactiveform.validate = function(form, successCallback, errorCallback) {
		var $form = $(form);
		var settings = $form.data('settings');
		$.ajax({
			url : settings.validationUrl,
			type : $form.attr('method'),
			data : $form.serialize()+'&'+settings.ajaxVar+'='+$form.attr('id'),
			dataType : 'json',
			success : function(data) {
				if (data != null && typeof data == 'object') {
					successCallback(data);
				}
			},
			error : function() {
				if (errorCallback!=undefined) {
					errorCallback();
				}
			}
		});
	};

	/**
	 * Returns the configuration for the specified form.
	 * The configuration contains all needed information to perform ajax-based validation.
	 * @param jquery the jquery representation of the form
	 * @return object the configuration for the specified form.
	 */
	$.fn.yiiactiveform.getSettings = function(form) {
		return $(form).data('settings');
	};

	$.fn.yiiactiveform.defaults = {
		ajaxVar: 'ajax',
		validationUrl: undefined,
		validationDelay: 100,
		validateOnSubmit : false,
		validateOnChange : true,
		validateOnType : false,
		hideErrorMessage : false,
		inputContainer : undefined,
		errorCssClass : 'error',
		successCssClass : 'success',
		validatingCssClass : 'validating',
		summaryID : undefined,
		timer: undefined,
		beforeValidateAttribute: undefined, // function(form, attribute) : boolean
		afterValidateAttribute: undefined,  // function(form, attribute, data, hasError)
		beforeValidate: undefined, // function(form) : boolean
		afterValidate: undefined,  // function(form, data, hasError) : boolean
		/**
		 * list of attributes to be validated. Each array element is of the following structure:
		 * {
		 *     inputID : 'input-tag-id',
		 *     errorID : 'error-tag-id',
		 *     value : undefined,
		 *     status : 0,  // 0: empty, not entered before,  1: validated, 2: pending validation, 3: validating
		 *     validationDelay: 100,
		 *     validateOnChange : true,
		 *     validateOnType : false,
		 *     hideErrorMessage : false,
		 *     inputContainer : undefined,
		 *     errorCssClass : 'error',
		 *     successCssClass : 'success',
		 *     validatingCssClass : 'validating',
		 *     beforeValidateAttribute: undefined, // function(form, attribute) : boolean
		 *     afterValidateAttribute: undefined,  // function(form, attribute, data, hasError)
		 * }
		 */
		attributes : []
	};

})(jQuery);<commit_msg><commit_after>/**
 * jQuery yiiactiveform plugin file.
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @link http://www.yiiframework.com/
 * @copyright Copyright © 2008-2010 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 * @version $Id$
 * @since 1.1.1
 */

;(function($) {
	/**
	 * yiiactiveform set function.
	 * @param map settings for the active form plugin. Please see {@link CActiveForm::options} for availablel options.
	 */
	$.fn.yiiactiveform = function(options) {
		return this.each(function() {
			var settings = $.extend({}, $.fn.yiiactiveform.defaults, options || {});
			var $form = $(this);
			var id = $form.attr('id');
			if(settings.validationUrl == undefined)
				settings.validationUrl = $form.attr('action');
			$.each(settings.attributes, function(i,attribute){
				settings.attributes[i] = $.extend({
					validationDelay : settings.validationDelay,
					validateOnChange : settings.validateOnChange,
					validateOnType : settings.validateOnType,
					hideErrorMessage : settings.hideErrorMessage,
					inputContainer : settings.inputContainer,
					errorCssClass : settings.errorCssClass,
					successCssClass : settings.successCssClass,
					beforeValidateAttribute : settings.beforeValidateAttribute,
					afterValidateAttribute : settings.afterValidateAttribute,
					validatingCssClass : settings.validatingCssClass
				}, attribute);
				settings.attributes[i].value = $('#'+attribute.inputID).val();
			});
			$(this).data('settings', settings);

			var validate = function(attribute, forceValidate) {
				if (forceValidate)
					attribute.status = 2;
				$.each(settings.attributes, function(){
					if (this.value != $('#'+this.inputID).val()) {
						this.status = 2;
						forceValidate = true;
					}
				});
				if (!forceValidate)
					return;

				if(settings.timer!=undefined) {
					clearTimeout(settings.timer);
				}

				settings.timer = setTimeout(function(){
					if(attribute.beforeValidateAttribute==undefined || attribute.beforeValidateAttribute($form, attribute)) {
						$.each(settings.attributes, function(){
							if (this.status == 2) {
								this.status = 3;
								$.fn.yiiactiveform.getInputContainer(this).addClass(this.validatingCssClass);
							}
						});
						$.fn.yiiactiveform.validate($form, function(data) {
							var hasError=false;
							$.each(settings.attributes, function(){
								if (this.status > 0) {
									hasError = $.fn.yiiactiveform.updateInput(this, data) || hasError;
								}
							});
							if(attribute.afterValidateAttribute!=undefined) {
								attribute.afterValidateAttribute($form,attribute,data,hasError);
							}
						});
					};
				}, attribute.validationDelay);
			};

			$.each(settings.attributes, function(i, attribute) {
				if (attribute.validateOnChange) {
					$('#'+attribute.inputID).change(function(){
						validate(attribute,false);
					}).blur(function(){
						if(attribute.status!=2 && attribute.status!=3)
							validate(attribute, !attribute.status);
					});
				}
				if (attribute.validateOnType) {
					$('#'+attribute.inputID).keyup(function(){
						if (attribute.value != $('#'+attribute.inputID).val())
							validate(attribute, false);
					});
				}
			});

			if (settings.validateOnSubmit) {
				$form.find(':submit').live('mouseup keyup',function(){
					$form.data('submitObject',$(this));
				});
				var validated = false;
				$form.submit(function(){
					if (validated)
						return true;
					if(settings.beforeValidate==undefined || settings.beforeValidate($form)) {
						$.fn.yiiactiveform.validate($form, function(data){
							var hasError = false;
							$.each(settings.attributes, function(i, attribute){
								hasError = $.fn.yiiactiveform.updateInput(attribute, data) || hasError;
							});
							$.fn.yiiactiveform.updateSummary($form, data);
							if(settings.afterValidate==undefined || settings.afterValidate($form, data, hasError)) {
								if(!hasError) {
									validated = true;
									var $button = $form.data('submitObject') || $form.find(':submit:first');
									// TODO: if the submission is caused by "change" event, it will not work
									if ($button.length)
										$button.click();
									else  // no submit button in the form
										$form.submit();
								}
							}
						});
					}
					return false;
				});
			}
		});
	};

	/**
	 * Returns the container element of the specified attribute.
	 * @param object the configuration for a particular attribute.
	 * @return jquery the jquery representation of the container
	 */
	$.fn.yiiactiveform.getInputContainer = function(attribute) {
		if(attribute.inputContainer == undefined)
			return $('#'+attribute.inputID).closest('div');
		else
			return $(attribute.inputContainer).filter(':has("#'+attribute.inputID+'")');
	};

	/**
	 * updates the error message and the input container for a particular attribute.
	 * @param object the configuration for a particular attribute.
	 * @param array the json data obtained from the ajax validation request
	 * @return boolean whether there is a validation error for the specified attribute
	 */
	$.fn.yiiactiveform.updateInput = function(attribute, messages) {
		attribute.status = 1;
		var hasError = messages!=null && $.isArray(messages[attribute.inputID]) && messages[attribute.inputID].length>0;
		var $error = $('#'+attribute.errorID);
		var $container = $.fn.yiiactiveform.getInputContainer(attribute);
		$container.removeClass(attribute.validatingCssClass)
			.removeClass(attribute.errorCssClass)
			.removeClass(attribute.successCssClass);

		if(hasError) {
			$error.html(messages[attribute.inputID][0]);
			$container.addClass(attribute.errorCssClass);
		}
		else {
			$container.addClass(attribute.successCssClass);
		}
		if(!attribute.hideErrorMessage)
			$error.toggle(hasError);

		attribute.value = $('#'+attribute.inputID).val();

		return hasError;
	};

	/**
	 * updates the error summary, if any.
	 * @param jquery the jquery representation of the form
	 * @param array the json data obtained from the ajax validation request
	 */
	$.fn.yiiactiveform.updateSummary = function(form, messages) {
		var settings = $(form).data('settings');
		if (settings.summaryID == undefined)
			return;
		var content = '';
		$.each(settings.attributes, function(i, attribute){
			if(messages && $.isArray(messages[attribute.inputID])) {
				$.each(messages[attribute.inputID],function(j,message){
					content = content + '
' + message + '
';
				});
			}
		});
		$('#'+settings.summaryID+' ul').html(content);
		$('#'+settings.summaryID).toggle(content!='');
	};

	/**
	 * Performs the ajax validation request.
	 * This method is invoked internally to trigger the ajax validation.
	 * @param jquery the jquery representation of the form
	 * @param function the function to be invoked if the ajax request succeeds
	 * @param function the function to be invoked if the ajax request fails
	 */
	$.fn.yiiactiveform.validate = function(form, successCallback, errorCallback) {
		var $form = $(form);
		var settings = $form.data('settings');
		$.ajax({
			url : settings.validationUrl,
			type : $form.attr('method'),
			data : $form.serialize()+'&'+settings.ajaxVar+'='+$form.attr('id'),
			dataType : 'json',
			success : function(data) {
				if (data != null && typeof data == 'object') {
					successCallback(data);
				}
			},
			error : function() {
				if (errorCallback!=undefined) {
					errorCallback();
				}
			}
		});
	};

	/**
	 * Returns the configuration for the specified form.
	 * The configuration contains all needed information to perform ajax-based validation.
	 * @param jquery the jquery representation of the form
	 * @return object the configuration for the specified form.
	 */
	$.fn.yiiactiveform.getSettings = function(form) {
		return $(form).data('settings');
	};

	$.fn.yiiactiveform.defaults = {
		ajaxVar: 'ajax',
		validationUrl: undefined,
		validationDelay: 100,
		validateOnSubmit : false,
		validateOnChange : true,
		validateOnType : false,
		hideErrorMessage : false,
		inputContainer : undefined,
		errorCssClass : 'error',
		successCssClass : 'success',
		validatingCssClass : 'validating',
		summaryID : undefined,
		timer: undefined,
		beforeValidateAttribute: undefined, // function(form, attribute) : boolean
		afterValidateAttribute: undefined,  // function(form, attribute, data, hasError)
		beforeValidate: undefined, // function(form) : boolean
		afterValidate: undefined,  // function(form, data, hasError) : boolean
		/**
		 * list of attributes to be validated. Each array element is of the following structure:
		 * {
		 *     inputID : 'input-tag-id',
		 *     errorID : 'error-tag-id',
		 *     value : undefined,
		 *     status : 0,  // 0: empty, not entered before,  1: validated, 2: pending validation, 3: validating
		 *     validationDelay: 100,
		 *     validateOnChange : true,
		 *     validateOnType : false,
		 *     hideErrorMessage : false,
		 *     inputContainer : undefined,
		 *     errorCssClass : 'error',
		 *     successCssClass : 'success',
		 *     validatingCssClass : 'validating',
		 *     beforeValidateAttribute: undefined, // function(form, attribute) : boolean
		 *     afterValidateAttribute: undefined,  // function(form, attribute, data, hasError)
		 * }
		 */
		attributes : []
	};

})(jQuery);<|endoftext|>


<commit_before>/**
 * @class UI.Control.Button
 * @extends {UI.Control}
 * @type {Class}
 */
define([
	'UI/Control/Control'
], function(
	Control
) {

	var _log = __debug('ui:control-button');

	var exports = new Class({

		Extends: Control,

		name: 'button',

		options: {
			name: 'button',
			type: null, // push, file
			ink: true,
			element: {
				tag: 'span'
			},
			binding: {
				_list: ['element'],
				element: {
					'sensor.click': '_onClick',
					'sensor.dblclick': '_onDblClick',
					'sensor.mousedown': '_onMouseDown',
					'sensor.mouseup': '_onMouseUp',
					'sensor.mouseleave': '_onMouseLeave'
				}
			}
		},

		/**
		 * [set description]
		 */
		set: function() {},

		/**
		 * [_initElement description]
		 * @return {void}
		 */
		_initElement: function() {
			this.parent();

			var opts = this.options;
			var type = opts.type;

			opts.text = opts.text || opts.n;

			if (type === null) {
				type = 'icon-text';
			}

			/*if (opts.text && type != 'icon') {
				this.element.set('html', opts.text);
			}*/
			//var text = opts.type.match(/text/g);

			if (opts.name) {
				this.element.set('data-name', opts.name);
			}

			_log.debug('title', this.element, opts.text);

			this.element.set('title', opts.text);

			if (opts.icon) {
				this._initIcon(type, opts.name);
			}

			if (opts.text) {
				this._initText(type);
			}

			if (opts.ink) {
				this._initSensor();
			} else {
				this.sensor = this.element;
			}
		},

		/**
		 * [_initIcon description]
		 * @param  {string} type
		 * @return {string}
		 */
		_initIcon: function(type, name) {
			_log.debug('_initIcon', type, name);

			var tag = 'span';
			var code = name;
			var klss = null;

			var prop = {
				'class': 'ui-icon'
			};

			this.icon = new Element(tag, prop).inject(this.element);

			if (mnml.icon.mdi[name]) {
				//_log.debug('mdi');
				klss = 'icon-mdi';
				code = mnml.icon.mdi[name];
			} else if (mnml.icon.font[name]) {
				//_log.debug('iocn font name', name);
				klss = 'icon-font';
				code = mnml.icon.font[name];
			}

			if (klss) {
				this.icon.addClass(klss);
			}

			if (code) {
				this.icon.addClass(code);
			}
		},

		/**
		 * [_initText description]
		 * @param  {string} type
		 * @return {void}
		 */
		_initText: function(type) {
			var opts = this.options;

			var tag = 'span';

			var pos = 'bottom';
			if (type === 'text-icon') {
				pos = 'top';
			}

			this.text = new Element(tag, {
				'class': 'ui-text',
				'html': opts.text
			}).inject(this.element, pos);
		},

		/**
		 * [_initClass description]
		 * @return {void}
		 */
		_initClass: function() {
			var opts = this.options;
			//_log.debug(this.name);

			if (this.options.isPrimary) {
				this.element.addClass('is-primary');
			}

			if (this.options.klss) {
				this.element.addClass(opts.klss);
			}

			if (this.options.type) {
				this.element.addClass('type-' + this.options.type);
			}

			this.element.addClass(opts.prefix + this.name);

			if (this.options.clss) {
				this.element.addClass(this.options.clss);
			}
		},

		/**
		 * [_initText description]
		 * @return {void}
		 */
		_initSensor: function() {
			_log.debug('_initSensor');

			var tag = 'div';

			this.sensor = new Element(tag, {
				'class': 'ui-sensor',
			}).inject(this.element);
		},

		/**
		 * [_initEffect description]
		 * @param  {string} ink
		 * @param  {string} x
		 * @param  {string} y
		 * @param  {Object} coord
		 * @return {void}
		 */
		_touchInk: function(ink, x, y, coord) {
			var size = coord.height;
			var top = 0;
			var duration = 1000;

			this.ink = ink;

			if (coord.width > size) {
				size = coord.width;
				top = (coord.height - coord.width) / 2;
			}

			var fx = new Fx.Morph(ink, {
				duration: duration,
				link: 'chain',
				transition: Fx.Transitions.Quart.easeOut
			});

			fx.start({
				height: size,
				width: size,
				left: 0,
				top: top,
				opacity: 0
			});

			(function() {
				ink.destroy();
			}).delay(duration);
		},

		/**
		 * [_onElementMouseDown description]
		 * @param  {event} e
		 * @return {void}
		 */
		_onClick: function(e) {
			_log.debug('_onElementClick', e);

			var opts = this.options;

			e.stopPropagation();

			if (opts.emit && this.state !== 'disabled') {
				this.fireEvent(opts.emit);
			}
			this.fireEvent('press', opts.emit);
			this.fireEvent('pressed', opts.emit);

			if (opts.call && this.state !== 'disabled') {
				opts.call();
			}
		},

		/**
		 * [_onElementMouseDown description]
		 * @param  {event} e
		 * @return {void}
		 */
		_onDblClick: function(e) {
			var opts = this.options;

			e.stop();

			if (opts.emit && this.state !== 'disabled') {
				this.fireEvent('dblpress', opts.emit);
			}

			this.fireEvent('dblpressed', opts.emit);
		},

		/**
		 * [_onElementMouseDown description]
		 * @param  {event} e
		 * @return {Object}
		 */
		_onMouseDown: function(e) {
			//_log.debug('_onElementMouseDown', e);

			e.stop();

			if (this.state === 'disabled') {
				return;
			}

			var x = e.event.offsetX;
			var y = e.event.offsetY;

			var coord = this.element.getCoordinates(this.element);

			var ink = this.ink = new Element('span', {
				class: 'ui-ink',
				styles: {
					left: x,
					top: y
				}
			}).inject(this.element, 'top');

			this._touchInk(ink, x, y, coord);

			this.fireEvent('mousedown');
		},

		/**
		 * [_onElementMouseDown description]
		 * @param  {event} e
		 * @return {void}
		 */
		_onMouseLeave: function(e) {
			_log.debug('_onMouseLeave', e);

		},

		/**
		 * [_onElementMouseDown description]
		 * @param  {event} e
		 * @return {void}
		 */
		_onMouseEnter: function(e) {
			_log.debug('_onElementMouseDown', e);

		},

		/**
		 * [_onElementMouseUp description]
		 * @return {void}
		 */
		_onMouseUp: function(e) {
			_log.debug('_onElementMouseUp', e);

			if (this.options.type === 'check') {
				if (this.state === 'checked') {
					this.setState(null);
				} else {
					this.setState('checked');
				}
			}

			//this.react.destroy();
		}

	});

	return exports;
});
<commit_msg>ui button use icon from opts instead of name<commit_after>/**
 * @class UI.Control.Button
 * @extends {UI.Control}
 * @type {Class}
 */
define([
	'UI/Control/Control'
], function(
	Control
) {

	var _log = __debug('ui:control-button');

	var exports = new Class({

		Extends: Control,

		name: 'button',

		options: {
			name: 'button',
			type: null, // push, file
			ink: true,
			element: {
				tag: 'span'
			},
			binding: {
				_list: ['element'],
				element: {
					'sensor.click': '_onClick',
					'sensor.dblclick': '_onDblClick',
					'sensor.mousedown': '_onMouseDown',
					'sensor.mouseup': '_onMouseUp',
					'sensor.mouseleave': '_onMouseLeave'
				}
			}
		},

		/**
		 * [set description]
		 */
		set: function() {},

		/**
		 * [_initElement description]
		 * @return {void}
		 */
		_initElement: function() {
			this.parent();

			var opts = this.options;
			var type = opts.type;

			opts.text = opts.text || opts.n;

			if (type === null) {
				type = 'icon-text';
			}

			/*if (opts.text && type != 'icon') {
				this.element.set('html', opts.text);
			}*/
			//var text = opts.type.match(/text/g);

			if (opts.name) {
				this.element.set('data-name', opts.name);
			}

			_log.debug('title', this.element, opts.text);

			this.element.set('title', opts.text);

			if (opts.icon) {
				this._initIcon(type, opts.icon || opts.name);
			}

			if (opts.text) {
				this._initText(type);
			}

			if (opts.ink) {
				this._initSensor();
			} else {
				this.sensor = this.element;
			}
		},

		/**
		 * [_initIcon description]
		 * @param  {string} type
		 * @return {string}
		 */
		_initIcon: function(type, name) {
			_log.debug('_initIcon', type, name);

			var tag = 'span';
			var code = name;
			var klss = null;

			var prop = {
				'class': 'ui-icon'
			};

			this.icon = new Element(tag, prop).inject(this.element);

			if (mnml.icon.mdi[name]) {
				//_log.debug('mdi');
				klss = 'icon-mdi';
				code = mnml.icon.mdi[name];
			} else if (mnml.icon.font[name]) {
				//_log.debug('iocn font name', name);
				klss = 'icon-font';
				code = mnml.icon.font[name];
			}

			if (klss) {
				this.icon.addClass(klss);
			}

			if (code) {
				this.icon.addClass(code);
			}
		},

		/**
		 * [_initText description]
		 * @param  {string} type
		 * @return {void}
		 */
		_initText: function(type) {
			var opts = this.options;

			var tag = 'span';

			var pos = 'bottom';
			if (type === 'text-icon') {
				pos = 'top';
			}

			this.text = new Element(tag, {
				'class': 'ui-text',
				'html': opts.text
			}).inject(this.element, pos);
		},

		/**
		 * [_initClass description]
		 * @return {void}
		 */
		_initClass: function() {
			var opts = this.options;
			//_log.debug(this.name);

			if (this.options.isPrimary) {
				this.element.addClass('is-primary');
			}

			if (this.options.klss) {
				this.element.addClass(opts.klss);
			}

			if (this.options.type) {
				this.element.addClass('type-' + this.options.type);
			}

			this.element.addClass(opts.prefix + this.name);

			if (this.options.clss) {
				this.element.addClass(this.options.clss);
			}
		},

		/**
		 * [_initText description]
		 * @return {void}
		 */
		_initSensor: function() {
			_log.debug('_initSensor');

			var tag = 'div';

			this.sensor = new Element(tag, {
				'class': 'ui-sensor',
			}).inject(this.element);
		},

		/**
		 * [_initEffect description]
		 * @param  {string} ink
		 * @param  {string} x
		 * @param  {string} y
		 * @param  {Object} coord
		 * @return {void}
		 */
		_touchInk: function(ink, x, y, coord) {
			var size = coord.height;
			var top = 0;
			var duration = 1000;

			this.ink = ink;

			if (coord.width > size) {
				size = coord.width;
				top = (coord.height - coord.width) / 2;
			}

			var fx = new Fx.Morph(ink, {
				duration: duration,
				link: 'chain',
				transition: Fx.Transitions.Quart.easeOut
			});

			fx.start({
				height: size,
				width: size,
				left: 0,
				top: top,
				opacity: 0
			});

			(function() {
				ink.destroy();
			}).delay(duration);
		},

		/**
		 * [_onElementMouseDown description]
		 * @param  {event} e
		 * @return {void}
		 */
		_onClick: function(e) {
			_log.debug('_onElementClick', e);

			var opts = this.options;

			e.stopPropagation();

			if (opts.emit && this.state !== 'disabled') {
				this.fireEvent(opts.emit);
			}
			this.fireEvent('press', opts.emit);
			this.fireEvent('pressed', opts.emit);

			if (opts.call && this.state !== 'disabled') {
				opts.call();
			}
		},

		/**
		 * [_onElementMouseDown description]
		 * @param  {event} e
		 * @return {void}
		 */
		_onDblClick: function(e) {
			var opts = this.options;

			e.stop();

			if (opts.emit && this.state !== 'disabled') {
				this.fireEvent('dblpress', opts.emit);
			}

			this.fireEvent('dblpressed', opts.emit);
		},

		/**
		 * [_onElementMouseDown description]
		 * @param  {event} e
		 * @return {Object}
		 */
		_onMouseDown: function(e) {
			//_log.debug('_onElementMouseDown', e);

			e.stop();

			if (this.state === 'disabled') {
				return;
			}

			var x = e.event.offsetX;
			var y = e.event.offsetY;

			var coord = this.element.getCoordinates(this.element);

			var ink = this.ink = new Element('span', {
				class: 'ui-ink',
				styles: {
					left: x,
					top: y
				}
			}).inject(this.element, 'top');

			this._touchInk(ink, x, y, coord);

			this.fireEvent('mousedown');
		},

		/**
		 * [_onElementMouseDown description]
		 * @param  {event} e
		 * @return {void}
		 */
		_onMouseLeave: function(e) {
			_log.debug('_onMouseLeave', e);

		},

		/**
		 * [_onElementMouseDown description]
		 * @param  {event} e
		 * @return {void}
		 */
		_onMouseEnter: function(e) {
			_log.debug('_onElementMouseDown', e);

		},

		/**
		 * [_onElementMouseUp description]
		 * @return {void}
		 */
		_onMouseUp: function(e) {
			_log.debug('_onElementMouseUp', e);

			if (this.options.type === 'check') {
				if (this.state === 'checked') {
					this.setState(null);
				} else {
					this.setState('checked');
				}
			}

			//this.react.destroy();
		}

	});

	return exports;
});
<|endoftext|>


<commit_before>//* @protected
enyo.$ = {};

enyo.dispatcher = {
	// these events come from document
	events: ["mousedown", "mouseup", "mouseover", "mouseout", "mousemove", "mousewheel",
		"click", "dblclick", "change", "keydown", "keyup", "keypress", "input"],
	// these events come from window
	windowEvents: ["resize", "load", "unload", "message", "hashchange"],
	// these events come from css
	cssEvents: ["webkitTransitionEnd", "transitionend"],
	// feature plugins (aka filters)
	features: [],
	connect: function() {
		var d = enyo.dispatcher, i, n;
		for (i=0; (n=d.events[i]); i++) {
			d.listen(document, n);
		}
		for (i=0; (n=d.cssEvents[i]); i++) {
			d.listen(document, n);
		}
		for (i=0; (n=d.windowEvents[i]); i++) {
			// Chrome Packaged Apps don't like "unload"
			if(n === "unload" &&
				(typeof window.chrome === "object") &&
				window.chrome.app) {
				continue;
			}

			d.listen(window, n);
		}
		for (i=0; (n=d.cssEvents[i]); i++) {
			d.listen(document, n);
		}
	},
	listen: function(inListener, inEventName, inHandler) {
		var d = enyo.dispatch;
		if (inListener.addEventListener) {
			this.listen = function(inListener, inEventName, inHandler) {
				inListener.addEventListener(inEventName, inHandler || d, false);
			};
		} else {
			//enyo.log("IE8 COMPAT: using 'attachEvent'");
			this.listen = function(inListener, inEvent, inHandler) {
				inListener.attachEvent("on" + inEvent, function(e) {
					e.target = e.srcElement;
					if (!e.preventDefault) {
						e.preventDefault = enyo.iePreventDefault;
					}
					return (inHandler || d)(e);
				});
			};
		}
		this.listen(inListener, inEventName, inHandler);
	},
	stopListening: function(inListener, inEventName, inHandler) {
		var d = enyo.dispatch;
		if (inListener.addEventListener) {
			this.stopListening = function(inListener, inEventName, inHandler) {
				inListener.removeEventListener(inEventName, inHandler || d, false);
			};
		} else {
			//enyo.log("IE8 COMPAT: using 'detachEvent'");
			this.stopListening = function(inListener, inEvent, inHandler) {
				inListener.detachEvent("on" + inEvent, inHandler || d);
			};
		}
		this.stopListening(inListener, inEventName, inHandler);
	},
	//* Fires an event for Enyo to listen for.
	dispatch: function(e) {
		// Find the control who maps to e.target, or the first control that maps to an ancestor of e.target.
		var c = this.findDispatchTarget(e.target) || this.findDefaultTarget(e);
		// Cache the original target
		e.dispatchTarget = c;
		// support pluggable features return true to abort immediately or set e.preventDispatch to avoid processing.
		for (var i=0, fn; (fn=this.features[i]); i++) {
			if (fn.call(this, e) === true) {
				return;
			}
		}
		if (c && !e.preventDispatch) {
			this.dispatchBubble(e, c);
		}
	},
	//* Takes an Event.target and finds the corresponding Enyo control.
	findDispatchTarget: function(inNode) {
		var t, n = inNode;
		// FIXME: Mozilla: try/catch is here to squelch "Permission denied to access property xxx from a non-chrome context"
		// which appears to happen for scrollbar nodes in particular. It's unclear why those nodes are valid targets if
		// it is illegal to interrogate them. Would like to trap the bad nodes explicitly rather than using an exception block.
		try {
			while (n) {
				if ((t = enyo.$[n.id])) {
					// there could be multiple nodes with this id, the relevant node for this event is n
					// we don't push this directly to t.node because sometimes we are just asking what
					// the target 'would be' (aka, calling findDispatchTarget from handleMouseOverOut)
					t.eventNode = n;
					break;
				}
				n = n.parentNode;
			}
		} catch(x) {
			enyo.log(x, n);
		}
		return t;
	},
	//* Returns the default Enyo control for events.
	findDefaultTarget: function(e) {
		return enyo.master;
	},
	dispatchBubble: function(e, c) {
		return c.bubble("on" + e.type, e, c);
	}
};

// called in the context of an event
enyo.iePreventDefault = function() {
	try {
		this.returnValue = false;
	}
	catch(e) {
		// do nothing
	}
};

enyo.dispatch = function(inEvent) {
	return enyo.dispatcher.dispatch(inEvent);
};

enyo.bubble = function(inEvent) {
	// '|| window.event' clause needed for IE8
	var e = inEvent || window.event;
	if (e) {
		// We depend on e.target existing for event tracking and dispatching.
		if (!e.target) {
			e.target = e.srcElement;
		}
		enyo.dispatch(e);
	}
};

// This string is set on event handlers attributes for DOM elements that
// don't normally bubble (like onscroll) so that they can participate in the
// Enyo event system.
enyo.bubbler = "enyo.bubble(arguments[0])";

// The code below helps make Enyo compatible with Google Packages Apps
// Content Security Policy(http://developer.chrome.com/extensions/contentSecurityPolicy.html)
// which, among other things forbids use of inline scripts.
// We replace online scripting with equivalent means, leaving enyo.bubbler
// for backward compatibility.
(function() {
	var bubbleUp = function() {
		enyo.bubble(arguments[0]);
	};

	/**
	 * Makes given events bubble on specified enyo contol
	 */
	enyo.makeBubble = function() {
		var args = Array.prototype.slice.call(arguments, 0),
			control = args.shift();

		if((typeof control === "object") && (typeof control.hasNode === "function")) {
			enyo.forEach(args, function(event) {
				if(this.hasNode()) {
					enyo.dispatcher.listen(this.node, event, bubbleUp);
				}
			}, control);
		}
	};
	/**
	 * Removes the event listening and bubbling caused from enyo.makeBubble, on a specific control
	 */
	enyo.unmakeBubble = function() {
		var args = Array.prototype.slice.call(arguments, 0),
			control = args.shift();

		if((typeof control === "object") && (typeof control.hasNode === "function")) {
			enyo.forEach(args, function(event) {
				if(this.hasNode()) {
					enyo.dispatcher.stopListening(this.node, event, bubbleUp);
				}
			}, control);
		}
        };
})();

// FIXME: we need to create and initialize dispatcher someplace else to allow overrides
enyo.requiresWindow(enyo.dispatcher.connect);

// generate a tapped event for a raw-click event
enyo.dispatcher.features.push(
	function (e) {
		if ("click" === e.type) {
			if (e.clientX === 0 && e.clientY === 0) {
				// this allows the click to dispatch as well
				// but note the tap event will fire first
				var cp = enyo.clone(e);
				cp.type = "tap";
				enyo.dispatch(cp);
			}
		}
	}
);
<commit_msg>Spacing fix<commit_after>//* @protected
enyo.$ = {};

enyo.dispatcher = {
	// these events come from document
	events: ["mousedown", "mouseup", "mouseover", "mouseout", "mousemove", "mousewheel",
		"click", "dblclick", "change", "keydown", "keyup", "keypress", "input"],
	// these events come from window
	windowEvents: ["resize", "load", "unload", "message", "hashchange"],
	// these events come from css
	cssEvents: ["webkitTransitionEnd", "transitionend"],
	// feature plugins (aka filters)
	features: [],
	connect: function() {
		var d = enyo.dispatcher, i, n;
		for (i=0; (n=d.events[i]); i++) {
			d.listen(document, n);
		}
		for (i=0; (n=d.cssEvents[i]); i++) {
			d.listen(document, n);
		}
		for (i=0; (n=d.windowEvents[i]); i++) {
			// Chrome Packaged Apps don't like "unload"
			if(n === "unload" &&
				(typeof window.chrome === "object") &&
				window.chrome.app) {
				continue;
			}

			d.listen(window, n);
		}
		for (i=0; (n=d.cssEvents[i]); i++) {
			d.listen(document, n);
		}
	},
	listen: function(inListener, inEventName, inHandler) {
		var d = enyo.dispatch;
		if (inListener.addEventListener) {
			this.listen = function(inListener, inEventName, inHandler) {
				inListener.addEventListener(inEventName, inHandler || d, false);
			};
		} else {
			//enyo.log("IE8 COMPAT: using 'attachEvent'");
			this.listen = function(inListener, inEvent, inHandler) {
				inListener.attachEvent("on" + inEvent, function(e) {
					e.target = e.srcElement;
					if (!e.preventDefault) {
						e.preventDefault = enyo.iePreventDefault;
					}
					return (inHandler || d)(e);
				});
			};
		}
		this.listen(inListener, inEventName, inHandler);
	},
	stopListening: function(inListener, inEventName, inHandler) {
		var d = enyo.dispatch;
		if (inListener.addEventListener) {
			this.stopListening = function(inListener, inEventName, inHandler) {
				inListener.removeEventListener(inEventName, inHandler || d, false);
			};
		} else {
			//enyo.log("IE8 COMPAT: using 'detachEvent'");
			this.stopListening = function(inListener, inEvent, inHandler) {
				inListener.detachEvent("on" + inEvent, inHandler || d);
			};
		}
		this.stopListening(inListener, inEventName, inHandler);
	},
	//* Fires an event for Enyo to listen for.
	dispatch: function(e) {
		// Find the control who maps to e.target, or the first control that maps to an ancestor of e.target.
		var c = this.findDispatchTarget(e.target) || this.findDefaultTarget(e);
		// Cache the original target
		e.dispatchTarget = c;
		// support pluggable features return true to abort immediately or set e.preventDispatch to avoid processing.
		for (var i=0, fn; (fn=this.features[i]); i++) {
			if (fn.call(this, e) === true) {
				return;
			}
		}
		if (c && !e.preventDispatch) {
			this.dispatchBubble(e, c);
		}
	},
	//* Takes an Event.target and finds the corresponding Enyo control.
	findDispatchTarget: function(inNode) {
		var t, n = inNode;
		// FIXME: Mozilla: try/catch is here to squelch "Permission denied to access property xxx from a non-chrome context"
		// which appears to happen for scrollbar nodes in particular. It's unclear why those nodes are valid targets if
		// it is illegal to interrogate them. Would like to trap the bad nodes explicitly rather than using an exception block.
		try {
			while (n) {
				if ((t = enyo.$[n.id])) {
					// there could be multiple nodes with this id, the relevant node for this event is n
					// we don't push this directly to t.node because sometimes we are just asking what
					// the target 'would be' (aka, calling findDispatchTarget from handleMouseOverOut)
					t.eventNode = n;
					break;
				}
				n = n.parentNode;
			}
		} catch(x) {
			enyo.log(x, n);
		}
		return t;
	},
	//* Returns the default Enyo control for events.
	findDefaultTarget: function(e) {
		return enyo.master;
	},
	dispatchBubble: function(e, c) {
		return c.bubble("on" + e.type, e, c);
	}
};

// called in the context of an event
enyo.iePreventDefault = function() {
	try {
		this.returnValue = false;
	}
	catch(e) {
		// do nothing
	}
};

enyo.dispatch = function(inEvent) {
	return enyo.dispatcher.dispatch(inEvent);
};

enyo.bubble = function(inEvent) {
	// '|| window.event' clause needed for IE8
	var e = inEvent || window.event;
	if (e) {
		// We depend on e.target existing for event tracking and dispatching.
		if (!e.target) {
			e.target = e.srcElement;
		}
		enyo.dispatch(e);
	}
};

// This string is set on event handlers attributes for DOM elements that
// don't normally bubble (like onscroll) so that they can participate in the
// Enyo event system.
enyo.bubbler = "enyo.bubble(arguments[0])";

// The code below helps make Enyo compatible with Google Packages Apps
// Content Security Policy(http://developer.chrome.com/extensions/contentSecurityPolicy.html)
// which, among other things forbids use of inline scripts.
// We replace online scripting with equivalent means, leaving enyo.bubbler
// for backward compatibility.
(function() {
	var bubbleUp = function() {
		enyo.bubble(arguments[0]);
	};

	/**
	 * Makes given events bubble on specified enyo contol
	 */
	enyo.makeBubble = function() {
		var args = Array.prototype.slice.call(arguments, 0),
			control = args.shift();

		if((typeof control === "object") && (typeof control.hasNode === "function")) {
			enyo.forEach(args, function(event) {
				if(this.hasNode()) {
					enyo.dispatcher.listen(this.node, event, bubbleUp);
				}
			}, control);
		}
	};
	/**
	 * Removes the event listening and bubbling caused from enyo.makeBubble, on a specific control
	 */
	enyo.unmakeBubble = function() {
		var args = Array.prototype.slice.call(arguments, 0),
			control = args.shift();

		if((typeof control === "object") && (typeof control.hasNode === "function")) {
			enyo.forEach(args, function(event) {
				if(this.hasNode()) {
					enyo.dispatcher.stopListening(this.node, event, bubbleUp);
				}
			}, control);
		}
	};
})();

// FIXME: we need to create and initialize dispatcher someplace else to allow overrides
enyo.requiresWindow(enyo.dispatcher.connect);

// generate a tapped event for a raw-click event
enyo.dispatcher.features.push(
	function (e) {
		if ("click" === e.type) {
			if (e.clientX === 0 && e.clientY === 0) {
				// this allows the click to dispatch as well
				// but note the tap event will fire first
				var cp = enyo.clone(e);
				cp.type = "tap";
				enyo.dispatch(cp);
			}
		}
	}
);
<|endoftext|>


<commit_before>(function (enyo, source) {
	/**
	 * An [object]{@glossary Object} describing the the last known coordinates of the cursor or
	 * user-interaction point in touch environments.
	 *
	 * @typedef {Object} enyo.dispatcher~CursorCoordinates
	 * @property {Number} clientX - The horizontal coordinate within the application's client area.
	 * @property {Number} clientY - The vertical coordinate within the application's client area.
	 * @property {Number} pageX - The X coordinate of the cursor relative to the viewport, including any
	 *   scroll offset.
	 * @property {Number} pageY - The Y coordinate of the cursor relative to the viewport, including any
	 *   scroll offset.
	 * @property {Number} screenX - The X coordinate of the cursor relative to the screen, not including
	 *   any scroll offset.
	 * @property {Number} screenY - The Y coordinate of the cursor relative to the screen, not including
	 *   any scroll offset.
	 */

	/**
	* @private
	*/
	enyo.$ = {};

	/**
	* @private
	*/
	enyo.dispatcher =
		/** @lends enyo.dispatcher.prototype */ {

		/**
		* These events come from document
		*
		* @private
		*/
		events: ["mousedown", "mouseup", "mouseover", "mouseout", "mousemove", "mousewheel",
			"click", "dblclick", "change", "keydown", "keyup", "keypress", "input",
			"paste", "copy", "cut", "webkitTransitionEnd", "transitionend", "webkitAnimationEnd", "animationend",
			"webkitAnimationStart", "animationstart", "webkitAnimationIteration", "animationiteration"],

		/**
		* These events come from window
		*
		* @private
		*/
		windowEvents: ["resize", "load", "unload", "message", "hashchange", "popstate"],

		/**
		* Feature plugins (aka filters)
		*
		* @private
		*/
		features: [],

		/**
		* @private
		*/
		platformSpecific: function() {
			var d = enyo.dispatcher,
				webosWindowEvents = ["focus", "blur"];
			if (enyo.platform.webos >= 4) {
				// webos send focus/blue event for window but doesn't send for input field
				d.windowEvents = d.windowEvents.concat(webosWindowEvents);
			}
		},

		/**
		* @private
		*/
		connect: function() {
			var d = enyo.dispatcher, i, n;
			d.platformSpecific();
			for (i=0; (n=d.events[i]); i++) {
				d.listen(document, n);
			}
			for (i=0; (n=d.windowEvents[i]); i++) {
				// Chrome Packaged Apps don't like "unload"
				if(n === "unload" &&
					(typeof window.chrome === "object") &&
					window.chrome.app) {
					continue;
				}

				d.listen(window, n);
			}
		},

		/**
		* @private
		*/
		listen: function(inListener, inEventName, inHandler) {
			var d = enyo.dispatch;
			if (inListener.addEventListener) {
				this.listen = function(inListener, inEventName, inHandler) {
					inListener.addEventListener(inEventName, inHandler || d, false);
				};
			} else {
				//enyo.log("IE8 COMPAT: using 'attachEvent'");
				this.listen = function(inListener, inEvent, inHandler) {
					inListener.attachEvent("on" + inEvent, function(e) {
						e.target = e.srcElement;
						if (!e.preventDefault) {
							e.preventDefault = enyo.iePreventDefault;
						}
						return (inHandler || d)(e);
					});
				};
			}
			this.listen(inListener, inEventName, inHandler);
		},

		/**
		* @private
		*/
		stopListening: function(inListener, inEventName, inHandler) {
			var d = enyo.dispatch;
			if (inListener.addEventListener) {
				this.stopListening = function(inListener, inEventName, inHandler) {
					inListener.removeEventListener(inEventName, inHandler || d, false);
				};
			} else {
				//enyo.log("IE8 COMPAT: using 'detachEvent'");
				this.stopListening = function(inListener, inEvent, inHandler) {
					inListener.detachEvent("on" + inEvent, inHandler || d);
				};
			}
			this.stopListening(inListener, inEventName, inHandler);
		},

		/**
		* Fires an event for Enyo to listen for.
		*
		* @private
		*/
		dispatch: function(e) {
			// Find the control who maps to e.target, or the first control that maps to an ancestor of e.target.
			var c = this.findDispatchTarget(e.target) || this.findDefaultTarget();
			// Cache the original target
			e.dispatchTarget = c;
			// support pluggable features return true to abort immediately or set e.preventDispatch to avoid processing.
			for (var i=0, fn; (fn=this.features[i]); i++) {
				if (fn.call(this, e) === true) {
					return;
				}
			}
			if (c && !e.preventDispatch) {
				return this.dispatchBubble(e, c);
			}
		},

		/**
		* Takes an event target and finds the corresponding Enyo control.
		*
		* @private
		*/
		findDispatchTarget: function(inNode) {
			var t, n = inNode;
			// FIXME: Mozilla: try/catch is here to squelch "Permission denied to access property xxx from a non-chrome context"
			// which appears to happen for scrollbar nodes in particular. It's unclear why those nodes are valid targets if
			// it is illegal to interrogate them. Would like to trap the bad nodes explicitly rather than using an exception block.
			try {
				while (n) {
					if ((t = enyo.$[n.id])) {
						// there could be multiple nodes with this id, the relevant node for this event is n
						// we don't push this directly to t.node because sometimes we are just asking what
						// the target 'would be' (aka, calling findDispatchTarget from handleMouseOverOut)
						t.eventNode = n;
						break;
					}
					n = n.parentNode;
				}
			} catch(x) {
				enyo.log(x, n);
			}
			return t;
		},

		/**
		* Returns the default Enyo control for events.
		*
		* @private
		*/
		findDefaultTarget: function() {
			return enyo.master;
		},

		/**
		* @private
		*/
		dispatchBubble: function(e, c) {
			var type = e.type;
			type = e.customEvent ? type : "on" + type;
			return c.bubble(type, e, c);
		}
	};

	/**
	* Called in the context of an event.
	*
	* @private
	*/
	enyo.iePreventDefault = function() {
		try {
			this.returnValue = false;
		}
		catch(e) {
			// do nothing
		}
	};

	/**
	* @private
	*/
	enyo.dispatch = function(inEvent) {
		return enyo.dispatcher.dispatch(inEvent);
	};

	/**
	* @private
	*/
	enyo.bubble = function(inEvent) {
		// '|| window.event' clause needed for IE8
		var e = inEvent || window.event;
		if (e) {
			// We depend on e.target existing for event tracking and dispatching.
			if (!e.target) {
				e.target = e.srcElement;
			}
			enyo.dispatch(e);
		}
	};

	// This string is set on event handlers attributes for DOM elements that
	// don't normally bubble (like onscroll) so that they can participate in the
	// Enyo event system.
	enyo.bubbler = "enyo.bubble(arguments[0])";

	// The code below helps make Enyo compatible with Google Packaged Apps
	// Content Security Policy(http://developer.chrome.com/extensions/contentSecurityPolicy.html),
	// which, among other things, forbids the use of inline scripts.
	// We replace online scripting with equivalent means, leaving enyo.bubbler
	// for backward compatibility.
	(function() {
		var bubbleUp = function() {
			enyo.bubble(arguments[0]);
		};

		/**
		* Makes given events bubble on a specified Enyo control.
		*
		* @private
		*/
		enyo.makeBubble = function() {
			var args = Array.prototype.slice.call(arguments, 0),
				control = args.shift();

			if((typeof control === "object") && (typeof control.hasNode === "function")) {
				enyo.forEach(args, function(event) {
					if(this.hasNode()) {
						enyo.dispatcher.listen(this.node, event, bubbleUp);
					}
				}, control);
			}
		};

		/**
		* Removes the event listening and bubbling initiated by
		* [enyo.makeBubble()]{@link enyo.makeBubble} on a specific control.
		*
		* @private
		*/
		enyo.unmakeBubble = function() {
			var args = Array.prototype.slice.call(arguments, 0),
				control = args.shift();

			if((typeof control === "object") && (typeof control.hasNode === "function")) {
				enyo.forEach(args, function(event) {
					if(this.hasNode()) {
						enyo.dispatcher.stopListening(this.node, event, bubbleUp);
					}
				}, control);
			}
		};
	})();

	/**
	* @private
	*/
	// FIXME: we need to create and initialize dispatcher someplace else to allow overrides
	enyo.requiresWindow(enyo.dispatcher.connect);

	/**
	* Generates a tapped event for a raw-click event.
	*
	* @private
	*/
	enyo.dispatcher.features.push(
		function (e) {
			if ("click" === e.type) {
				if (e.clientX === 0 && e.clientY === 0) {
					// this allows the click to dispatch as well
					// but note the tap event will fire first
					var cp = enyo.clone(e);
					cp.type = "tap";
					cp.preventDefault = enyo.nop;
					enyo.dispatch(cp);
				}
			}
		}
	);

	/**
	* Instead of having multiple `features` pushed and handled in separate methods
	* for these events, we handle them uniformly here to expose the last known
	* interaction coordinates as accurately as possible.
	*
	* @private
	*/
	var _xy = {};
	enyo.dispatcher.features.push(
		function (e) {
			if (
				(e.type == "mousemove")  ||
				(e.type == "tap")        ||
				(e.type == "click")      ||
				(e.type == "touchmove")
			) {
				_xy.clientX = e.clientX;
				_xy.clientY = e.clientY;
				// note only ie8 does not support pageX/pageY
				_xy.pageX   = e.pageX;
				_xy.pageY   = e.pageY;
				// note ie8 and opera report these values incorrectly
				_xy.screenX = e.screenX;
				_xy.screenY = e.screenY;
			}
		}
	);

	/**
	* Retrieves the last known coordinates of the cursor or user-interaction point
	* in touch environments. Returns an immutable object with the `clientX`,
	* `clientY`, `pageX`, `pageY`, `screenX`, and `screenY` properties. It is
	* important to note that IE8 and Opera have improper reporting for the
	* `screenX` and `screenY` properties (they both use CSS pixels as opposed to
	* device pixels) and IE8 has no support for the `pageX` and `pageY` properties,
	* so they are facaded.
	*
	* @returns {enyo.dispatcher~CursorCoordinates} An [object]{@glossary Object} describing the
	*	the last known coordinates of the cursor or user-interaction point in touch environments.
	* @public
	*/
	enyo.getPosition = function () {
		var p = enyo.clone(_xy);
		// if we are in ie8 we facade the _pageX, pageY_ properties
		if (enyo.platform.ie < 9) {
			var d = (document.documentElement || document.body.parentNode || document.body);
			p.pageX = (p.clientX + d.scrollLeft);
			p.pageY = (p.clientY + d.scrollTop);
		}
		return p;
	};

})(enyo, this);
<commit_msg>ENYO-923: Stop marquee when window throw blur event<commit_after>(function (enyo, source) {
	/**
	 * An [object]{@glossary Object} describing the the last known coordinates of the cursor or
	 * user-interaction point in touch environments.
	 *
	 * @typedef {Object} enyo.dispatcher~CursorCoordinates
	 * @property {Number} clientX - The horizontal coordinate within the application's client area.
	 * @property {Number} clientY - The vertical coordinate within the application's client area.
	 * @property {Number} pageX - The X coordinate of the cursor relative to the viewport, including any
	 *   scroll offset.
	 * @property {Number} pageY - The Y coordinate of the cursor relative to the viewport, including any
	 *   scroll offset.
	 * @property {Number} screenX - The X coordinate of the cursor relative to the screen, not including
	 *   any scroll offset.
	 * @property {Number} screenY - The Y coordinate of the cursor relative to the screen, not including
	 *   any scroll offset.
	 */

	/**
	* @private
	*/
	enyo.$ = {};

	/**
	* @private
	*/
	enyo.dispatcher =
		/** @lends enyo.dispatcher.prototype */ {

		/**
		* These events come from document
		*
		* @private
		*/
		events: ["mousedown", "mouseup", "mouseover", "mouseout", "mousemove", "mousewheel",
			"click", "dblclick", "change", "keydown", "keyup", "keypress", "input",
			"paste", "copy", "cut", "webkitTransitionEnd", "transitionend", "webkitAnimationEnd", "animationend",
			"webkitAnimationStart", "animationstart", "webkitAnimationIteration", "animationiteration"],

		/**
		* These events come from window
		*
		* @private
		*/
		windowEvents: ["resize", "load", "unload", "message", "hashchange", "popstate", "focus", "blur"],

		/**
		* Feature plugins (aka filters)
		*
		* @private
		*/
		features: [],

		/**
		* @private
		*/
		connect: function() {
			var d = enyo.dispatcher, i, n;
			for (i=0; (n=d.events[i]); i++) {
				d.listen(document, n);
			}
			for (i=0; (n=d.windowEvents[i]); i++) {
				// Chrome Packaged Apps don't like "unload"
				if(n === "unload" &&
					(typeof window.chrome === "object") &&
					window.chrome.app) {
					continue;
				}

				d.listen(window, n);
			}
		},

		/**
		* @private
		*/
		listen: function(inListener, inEventName, inHandler) {
			var d = enyo.dispatch;
			if (inListener.addEventListener) {
				this.listen = function(inListener, inEventName, inHandler) {
					inListener.addEventListener(inEventName, inHandler || d, false);
				};
			} else {
				//enyo.log("IE8 COMPAT: using 'attachEvent'");
				this.listen = function(inListener, inEvent, inHandler) {
					inListener.attachEvent("on" + inEvent, function(e) {
						e.target = e.srcElement;
						if (!e.preventDefault) {
							e.preventDefault = enyo.iePreventDefault;
						}
						return (inHandler || d)(e);
					});
				};
			}
			this.listen(inListener, inEventName, inHandler);
		},

		/**
		* @private
		*/
		stopListening: function(inListener, inEventName, inHandler) {
			var d = enyo.dispatch;
			if (inListener.addEventListener) {
				this.stopListening = function(inListener, inEventName, inHandler) {
					inListener.removeEventListener(inEventName, inHandler || d, false);
				};
			} else {
				//enyo.log("IE8 COMPAT: using 'detachEvent'");
				this.stopListening = function(inListener, inEvent, inHandler) {
					inListener.detachEvent("on" + inEvent, inHandler || d);
				};
			}
			this.stopListening(inListener, inEventName, inHandler);
		},

		/**
		* Fires an event for Enyo to listen for.
		*
		* @private
		*/
		dispatch: function(e) {
			// Find the control who maps to e.target, or the first control that maps to an ancestor of e.target.
			var c = this.findDispatchTarget(e.target) || this.findDefaultTarget();
			// Cache the original target
			e.dispatchTarget = c;
			// support pluggable features return true to abort immediately or set e.preventDispatch to avoid processing.
			for (var i=0, fn; (fn=this.features[i]); i++) {
				if (fn.call(this, e) === true) {
					return;
				}
			}
			if (c && !e.preventDispatch) {
				return this.dispatchBubble(e, c);
			}
		},

		/**
		* Takes an event target and finds the corresponding Enyo control.
		*
		* @private
		*/
		findDispatchTarget: function(inNode) {
			var t, n = inNode;
			// FIXME: Mozilla: try/catch is here to squelch "Permission denied to access property xxx from a non-chrome context"
			// which appears to happen for scrollbar nodes in particular. It's unclear why those nodes are valid targets if
			// it is illegal to interrogate them. Would like to trap the bad nodes explicitly rather than using an exception block.
			try {
				while (n) {
					if ((t = enyo.$[n.id])) {
						// there could be multiple nodes with this id, the relevant node for this event is n
						// we don't push this directly to t.node because sometimes we are just asking what
						// the target 'would be' (aka, calling findDispatchTarget from handleMouseOverOut)
						t.eventNode = n;
						break;
					}
					n = n.parentNode;
				}
			} catch(x) {
				enyo.log(x, n);
			}
			return t;
		},

		/**
		* Returns the default Enyo control for events.
		*
		* @private
		*/
		findDefaultTarget: function() {
			return enyo.master;
		},

		/**
		* @private
		*/
		dispatchBubble: function(e, c) {
			var type = e.type;
			type = e.customEvent ? type : "on" + type;
			return c.bubble(type, e, c);
		}
	};

	/**
	* Called in the context of an event.
	*
	* @private
	*/
	enyo.iePreventDefault = function() {
		try {
			this.returnValue = false;
		}
		catch(e) {
			// do nothing
		}
	};

	/**
	* @private
	*/
	enyo.dispatch = function(inEvent) {
		return enyo.dispatcher.dispatch(inEvent);
	};

	/**
	* @private
	*/
	enyo.bubble = function(inEvent) {
		// '|| window.event' clause needed for IE8
		var e = inEvent || window.event;
		if (e) {
			// We depend on e.target existing for event tracking and dispatching.
			if (!e.target) {
				e.target = e.srcElement;
			}
			enyo.dispatch(e);
		}
	};

	// This string is set on event handlers attributes for DOM elements that
	// don't normally bubble (like onscroll) so that they can participate in the
	// Enyo event system.
	enyo.bubbler = "enyo.bubble(arguments[0])";

	// The code below helps make Enyo compatible with Google Packaged Apps
	// Content Security Policy(http://developer.chrome.com/extensions/contentSecurityPolicy.html),
	// which, among other things, forbids the use of inline scripts.
	// We replace online scripting with equivalent means, leaving enyo.bubbler
	// for backward compatibility.
	(function() {
		var bubbleUp = function() {
			enyo.bubble(arguments[0]);
		};

		/**
		* Makes given events bubble on a specified Enyo control.
		*
		* @private
		*/
		enyo.makeBubble = function() {
			var args = Array.prototype.slice.call(arguments, 0),
				control = args.shift();

			if((typeof control === "object") && (typeof control.hasNode === "function")) {
				enyo.forEach(args, function(event) {
					if(this.hasNode()) {
						enyo.dispatcher.listen(this.node, event, bubbleUp);
					}
				}, control);
			}
		};

		/**
		* Removes the event listening and bubbling initiated by
		* [enyo.makeBubble()]{@link enyo.makeBubble} on a specific control.
		*
		* @private
		*/
		enyo.unmakeBubble = function() {
			var args = Array.prototype.slice.call(arguments, 0),
				control = args.shift();

			if((typeof control === "object") && (typeof control.hasNode === "function")) {
				enyo.forEach(args, function(event) {
					if(this.hasNode()) {
						enyo.dispatcher.stopListening(this.node, event, bubbleUp);
					}
				}, control);
			}
		};
	})();

	/**
	* @private
	*/
	// FIXME: we need to create and initialize dispatcher someplace else to allow overrides
	enyo.requiresWindow(enyo.dispatcher.connect);

	/**
	* Generates a tapped event for a raw-click event.
	*
	* @private
	*/
	enyo.dispatcher.features.push(
		function (e) {
			if ("click" === e.type) {
				if (e.clientX === 0 && e.clientY === 0) {
					// this allows the click to dispatch as well
					// but note the tap event will fire first
					var cp = enyo.clone(e);
					cp.type = "tap";
					cp.preventDefault = enyo.nop;
					enyo.dispatch(cp);
				}
			}
		}
	);

	/**
	* Instead of having multiple `features` pushed and handled in separate methods
	* for these events, we handle them uniformly here to expose the last known
	* interaction coordinates as accurately as possible.
	*
	* @private
	*/
	var _xy = {};
	enyo.dispatcher.features.push(
		function (e) {
			if (
				(e.type == "mousemove")  ||
				(e.type == "tap")        ||
				(e.type == "click")      ||
				(e.type == "touchmove")
			) {
				_xy.clientX = e.clientX;
				_xy.clientY = e.clientY;
				// note only ie8 does not support pageX/pageY
				_xy.pageX   = e.pageX;
				_xy.pageY   = e.pageY;
				// note ie8 and opera report these values incorrectly
				_xy.screenX = e.screenX;
				_xy.screenY = e.screenY;
			}
		}
	);

	/**
	* Retrieves the last known coordinates of the cursor or user-interaction point
	* in touch environments. Returns an immutable object with the `clientX`,
	* `clientY`, `pageX`, `pageY`, `screenX`, and `screenY` properties. It is
	* important to note that IE8 and Opera have improper reporting for the
	* `screenX` and `screenY` properties (they both use CSS pixels as opposed to
	* device pixels) and IE8 has no support for the `pageX` and `pageY` properties,
	* so they are facaded.
	*
	* @returns {enyo.dispatcher~CursorCoordinates} An [object]{@glossary Object} describing the
	*	the last known coordinates of the cursor or user-interaction point in touch environments.
	* @public
	*/
	enyo.getPosition = function () {
		var p = enyo.clone(_xy);
		// if we are in ie8 we facade the _pageX, pageY_ properties
		if (enyo.platform.ie < 9) {
			var d = (document.documentElement || document.body.parentNode || document.body);
			p.pageX = (p.clientX + d.scrollLeft);
			p.pageY = (p.clientY + d.scrollTop);
		}
		return p;
	};

})(enyo, this);
<|endoftext|>


<commit_before>function nameDisplay (el) {
	if (el.querySelector('.tweet-detail')) {
		setTimeout(function() {
			var username = el.querySelector('.account-summary a[rel=user]').href.split('/').pop();
			var fullname = el.querySelector('.account-summary b.fullname').innerText;

			el.querySelector('span.username').innerText = fullname;
			el.querySelector('b.fullname').innerText = username;
		}, 0);

	} else if (el.querySelector('.fullname') && el.querySelector('.username')) {
		var fullname = el.querySelector('.fullname').innerText;
		// @TODO This produces an error when profil modals are opened and sometimes with tweets/RT
		var username = el.querySelector('header a[rel=user]').href.split('/').pop();
		el.querySelector('.username').innerText = fullname;
		el.querySelector('.fullname').innerText = username;

		if (el.querySelector('.tweet-context .nbfc a[rel=user]')) {
			var username = el.querySelector('.tweet-context .nbfc a[rel=user]').href.split('/').pop();

			el.querySelector('.tweet-context .nbfc a[rel=user]').innerText = username;
		} else if (el.querySelector('.nbfc a[rel=user]')) {
			var username = el.querySelector('.nbfc a[rel=user]').href.split('/').pop();

			el.querySelector('.nbfc a[rel=user]').innerText = username;
		}
	} else if (el.querySelector('.nbfc a[rel=user]') && (settings.name_display == "inverted" || settings.name_display == "username")) {
		var username = el.querySelector('a[rel=user]').href.split('/').pop();
		el.querySelector('.nbfc a[rel=user]').innerText = username;
	}
}<commit_msg>Fixed nameDisplay for direct messages<commit_after>function nameDisplay (el) {
	if (el.querySelector('.tweet-detail')) {
		setTimeout(function() {
			var username = el.querySelector('.account-summary a[rel=user]').href.split('/').pop();
			var fullname = el.querySelector('.account-summary b.fullname').innerHTML;

			el.querySelector('span.username').innerText = fullname;
			el.querySelector('b.fullname').innerText = username;
		}, 0);

	} else if ( (el.querySelector('.fullname') && el.querySelector('.username')) && el.querySelectorAll('ul.tweet-actions > *').length != 1) {
		var fullname = el.querySelector('.fullname').innerHTML;
		// @TODO This produces an error when profil modals are opened and sometimes with tweets/RT
		var username = el.querySelector('header a[rel=user]').href.split('/').pop();
		el.querySelector('.username').innerText = fullname;
		el.querySelector('.fullname').innerText = username;

		if (el.querySelector('.tweet-context .nbfc a[rel=user]')) {
			var username = el.querySelector('.tweet-context .nbfc a[rel=user]').href.split('/').pop();

			el.querySelector('.tweet-context .nbfc a[rel=user]').innerText = username;
		} else if (el.querySelector('.nbfc a[rel=user]')) {
			var username = el.querySelector('.nbfc a[rel=user]').href.split('/').pop();

			el.querySelector('.nbfc a[rel=user]').innerText = username;
		}
	} else if (el.querySelector('.nbfc a[rel=user]') && (settings.name_display == "inverted" || settings.name_display == "username")) {
		var username = el.querySelector('a[rel=user]').href.split('/').pop();
		el.querySelector('.nbfc a[rel=user]').innerText = username;
	} else if (el.querySelectorAll('ul.tweet-actions > *').length == 1) {
		var username = el.querySelector('a[rel=user]').href.split('/').pop();
		var fullname =  el.querySelector('b.fullname').innerHTML;
		el.querySelector('span.username').innerText = fullname;
		el.querySelector('b.fullname').innerHTML = username;
	}
}<|endoftext|>


<commit_before>(function () {

  //*@public
  /**
    An _enyo.Binding_ is a versatile object that creates an
    automatic propagation of changes between properties of
    a designated source or sources. Typically this object is
    exercised by a helper from _enyo.Object_ but can be
    instantiated independently if care is used to release
    object references and prevent memory leaks.

    TODO: complete docs
  */
  enyo.Binding = Binding;

  //*@protected
  function Binding () {
    var args = enyo.toArray(arguments), i = 0;
    for (; i < args.length; ++i) enyo.mixin(this, args[i]);
    enyo.bindingCount++;
    this.bindId = getBindingsId();
    this._setup();
  }

  enyo.bindingCount = 0;
  enyo.bindingsId = 0;

  var getParts, copyTransform, getBindingId;

  //*@protected
  /**
    The goal of this _enyo.Binding_ secure method is to
    take a given path (relative to optional _context_ which
    defaults to the _enyo.Binding_ _owner_ property if not
    provided in the definition), determine the object reference
    and the property on that reference as well as whether or
    not the target property is a _enyo.Computed_ property.
  */
  getParts = function (path, context) {
    // goal is to split the path and iterate over the parts
    // analyzing each piece until we reach the end
    path = path[0] === "."? path.slice(1): path;
    var parts = path.split("."), idx = 0, ret = {}, root, cur, prop, base, part;
    // the root is either the context passed in or the owner
    // of this method's caller
    root = context || this.owner;
    // initial starting place for the cur pointer
    base = root;
    // the property is assumed to be the last part of path
    // (or the entire path if no '.' is found)
    ret.property = prop = parts.length > 1? parts.pop(): path;
    if (prop === path) {
      ret.base = base;
    } else {
      for (; idx < parts.length; ++idx) {
        part = parts[idx];
        if (!part) continue;
        // update pointer
        cur = base[part];
        // if we can't find part of the path
        if (!cur || "string" === typeof cur) return ret;
        // update base pointer
        if (part !== path) base = cur;
        ret.base = base;
      }
    }
    return ret;
  };

  getBindingsId = function () {
    // TODO: possible source of failure?
    return String(enyo.bindingsId++);
  };

  copyTransform = function (data) {
    //return enyo.clone(data);
    return data;
  };

  Binding.prototype = {
    _target: null,
    _targetProperty: null,
    _targetResponder: null,
    _source: null,
    _sourceProperty: null,
    _sourceResponder: null,
    _waiting: null,
    _setup: function () {
      var s = this._setupSource(), t = this._setupTarget();
      if (!s || !t) return;
      if (this.autoConnect === true) this.connect();
      if (this.autoSync === true) this.sync();
    },
    _setupSource: function () {
      var parts = getParts.call(this, this.from, this.source), b, p;
      b = parts.base;
      p = parts.property;
      if (!b) {
        // this case is USUALLY ok because it means that a binding was
        // created BEFORE one the the source/target was not available yet
        // but the object will attempt again at a more appropriate time
        // this is an unfortunate by-product of the inheritance chain
        return false;
      }
      this._source = b;
      this._sourceProperty = p;
      return true;
    },
    _setupTarget: function () {
      var parts = getParts.call(this, this.to, this.target), b, p;
      b = parts.base;
      p = parts.property;
      if (!b) {
        return false;
      }
      this._target = b;
      this._targetProperty = p;
      return true;
    },
    _connectSource: function () {
      var s = this._source, sp = this._sourceProperty, sr = this._sourceResponder;

      if (!sr || !enyo.isFunction(sr)) {
        sr = this._sourceResponder = enyo.bind(this, this._syncFromSource);
      }

      if (!s) {
        // TODO: this needs to be monitored because the case where it showed up
        // was "ok" but there are probably times when this indicates a problem
        // NOTE: it was occuring when a row of a list-element was directly bound
        // to a property of its controller, a status change would take place, and
        // the list would re-render which destroys the view and the controller
        // and any observers/bindings but apparently the observer would fire anyways
        // and attempt to sync...
        return false;
      }

      sr.bindId = this.bindId;
      var o = sr;

      s.addObserver(sp, sr);
    },
    _connectTarget: function () {
      var t = this._target, tp = this._targetProperty, tr = this._targetResponder;
      if (this.oneWay === true) return;
      if (!tr || !enyo.isFunction(tr)) {
        tr = this._targetResponder = enyo.bind(this, this._syncFromTarget);
      }

      tr.bindId = this.bindId;

      t.addObserver(tp, tr);
    },

    _syncFromSource: function () {
      if (!this.oneWay) this._disconnectTarget();
      this.setTargetValue(this.getSourceValue());
      if (!this.oneWay) this._connectTarget();
    },
    _syncFromTarget: function () {
      this._disconnectSource();
      this.setSourceValue(this.getTargetValue());
      this._connectSource();
    },

    isConnected: false,
    isSynced: false,
    to: null,
    from: null,
    target: null,
    source: null,
    owner: null,
    autoConnect: false,
    autoSync: true,
    transform: null,
    oneWay: true,
    allowRefresh: true,

    sync: function (force) {
      if (this.isSynced && force !== true) return;
      this._syncFromSource();
      this.isSynced = true;
      return;
    },

    refresh: function () {
      if (!this.allowRefresh) return false;
      this.disconnect();
      this._setup();
    },

    connect: function () {
      if (this.isConnected) return;
      this._connectSource();
      this._connectTarget();
      this.isConnected = true;
    },

    disconnect: function () {
      this._disconnectSource();
      this._disconnectTarget();
      this.isSynced = false;
      this.isConnected = false;
    },

    _disconnectSource: function () {
      var sp = this._sourceProperty, sc = this._sourceComputedProperty;
      if (!this._source) return;
      this._source.removeObserver(sc || sp, this._sourceResponder);
    },

    _disconnectTarget: function () {
      if (!this._target) return;
      this._target.removeObserver(this._targetProperty, this._targetResponder);
    },

    suspend: function () {

    },

    getTargetValue: function () {
      //var r = enyo.getPath.call(this._target, this._targetProperty);

      if (!this._target) {
        enyo.error("no target", this);
      }

      var r = this._target.get(this._targetProperty);
      if (r instanceof Object) r = copyTransform(r);
      return r;
    },

    setTargetValue: function (inValue) {
      var v = this.transform && enyo.isFunction(this.transform)? this.transform(inValue, "target"): inValue;
      this.isSynced = true;
      return this._target.set(this._targetProperty, v, enyo.isArray(v));
    },

    getSourceValue: function () {
      var r, sp = this._sourceProperty, sc = this._sourceComputedProperty;
      //if (sc) r = enyo.getPath.call(this._source, sc)[sp];
      //else r = enyo.getPath.call(this._source, this._sourceProperty);
      if (sc) r = this._source.get(sc)[sp];
      else r = this._source.get(this._sourceProperty);
      if (r instanceof Object) r = copyTransform(r);
      return r;
    },

    setSourceValue: function (inValue) {
      var v = this.transform && enyo.isFunction(this.transform)? this.transform(inValue, "source"): inValue;
      return this._source.set(this._sourceProperty, v);
    },

    destroy: function () {
      this.disconnect();
      this._source = null;
      this._target = null;
      this._sourceResponder = null;
      this._targetResponder = null;
      this.isDestroyed = true;
      enyo.bindingCount--;

      if (this.owner) {
        this.owner.removeBinding(this);
      }
      //console.log("REMOVED A BINDING: ", enyo.bindingCount);
    }
  };

}());
<commit_msg>fix binding to properly determine source from path even if root is global<commit_after>(function () {

  //*@public
  /**
    An _enyo.Binding_ is a versatile object that creates an
    automatic propagation of changes between properties of
    a designated source or sources. Typically this object is
    exercised by a helper from _enyo.Object_ but can be
    instantiated independently if care is used to release
    object references and prevent memory leaks.

    TODO: complete docs
  */
  enyo.Binding = Binding;

  //*@protected
  function Binding () {
    var args = enyo.toArray(arguments), i = 0;
    for (; i < args.length; ++i) enyo.mixin(this, args[i]);
    enyo.bindingCount++;
    this.bindId = getBindingsId();
    this._setup();
  }

  enyo.bindingCount = 0;
  enyo.bindingsId = 0;

  var getParts, copyTransform, getBindingId;

  //*@protected
  /**
    The goal of this _enyo.Binding_ secure method is to
    take a given path (relative to optional _context_ which
    defaults to the _enyo.Binding_ _owner_ property if not
    provided in the definition), determine the object reference
    and the property on that reference as well as whether or
    not the target property is a _enyo.Computed_ property.
  */
  getParts = function (path, context) {
    // goal is to split the path and iterate over the parts
    // analyzing each piece until we reach the end
    path = path[0] === "."? path.slice(1): path;
    var parts = path.split("."), idx = 0, ret = {}, root, cur, prop, base, part;
    // the root is either the context passed in or the owner
    // of this method's caller
    root = context || (function (root) {return root[parts[0]]? root: undefined})(enyo.global) || this.owner;
    // initial starting place for the cur pointer
    base = root;
    // the property is assumed to be the last part of path
    // (or the entire path if no '.' is found)
    ret.property = prop = parts.length > 1? parts.pop(): path;
    if (prop === path) {
      ret.base = base;
    } else {
      for (; idx < parts.length; ++idx) {
        part = parts[idx];
        if (!part) continue;
        // update pointer
        cur = base[part];
        // if we can't find part of the path
        if (!cur || "string" === typeof cur) return ret;
        // update base pointer
        if (part !== path) base = cur;
        ret.base = base;
      }
    }
    return ret;
  };

  getBindingsId = function () {
    // TODO: possible source of failure?
    return String(enyo.bindingsId++);
  };

  copyTransform = function (data) {
    //return enyo.clone(data);
    return data;
  };

  Binding.prototype = {
    _target: null,
    _targetProperty: null,
    _targetResponder: null,
    _source: null,
    _sourceProperty: null,
    _sourceResponder: null,
    _waiting: null,
    _setup: function () {
      var s = this._setupSource(), t = this._setupTarget();
      if (!s || !t) return;
      if (this.autoConnect === true) this.connect();
      if (this.autoSync === true) this.sync();
    },
    _setupSource: function () {
      var parts = getParts.call(this, this.from, this.source), b, p;
      b = parts.base;
      p = parts.property;
      if (!b) {
        // this case is USUALLY ok because it means that a binding was
        // created BEFORE one the the source/target was not available yet
        // but the object will attempt again at a more appropriate time
        // this is an unfortunate by-product of the inheritance chain
        return false;
      }
      this._source = b;
      this._sourceProperty = p;
      return true;
    },
    _setupTarget: function () {
      var parts = getParts.call(this, this.to, this.target), b, p;
      b = parts.base;
      p = parts.property;
      if (!b) {
        return false;
      }
      this._target = b;
      this._targetProperty = p;
      return true;
    },
    _connectSource: function () {
      var s = this._source, sp = this._sourceProperty, sr = this._sourceResponder;

      if (!sr || !enyo.isFunction(sr)) {
        sr = this._sourceResponder = enyo.bind(this, this._syncFromSource);
      }

      if (!s) {
        // TODO: this needs to be monitored because the case where it showed up
        // was "ok" but there are probably times when this indicates a problem
        // NOTE: it was occuring when a row of a list-element was directly bound
        // to a property of its controller, a status change would take place, and
        // the list would re-render which destroys the view and the controller
        // and any observers/bindings but apparently the observer would fire anyways
        // and attempt to sync...
        return false;
      }

      sr.bindId = this.bindId;
      var o = sr;

      s.addObserver(sp, sr);
    },
    _connectTarget: function () {
      var t = this._target, tp = this._targetProperty, tr = this._targetResponder;
      if (this.oneWay === true) return;
      if (!tr || !enyo.isFunction(tr)) {
        tr = this._targetResponder = enyo.bind(this, this._syncFromTarget);
      }

      tr.bindId = this.bindId;

      t.addObserver(tp, tr);
    },

    _syncFromSource: function () {
      if (!this.oneWay) this._disconnectTarget();
      this.setTargetValue(this.getSourceValue());
      if (!this.oneWay) this._connectTarget();
    },
    _syncFromTarget: function () {
      this._disconnectSource();
      this.setSourceValue(this.getTargetValue());
      this._connectSource();
    },

    isConnected: false,
    isSynced: false,
    to: null,
    from: null,
    target: null,
    source: null,
    owner: null,
    autoConnect: false,
    autoSync: true,
    transform: null,
    oneWay: true,
    allowRefresh: true,

    sync: function (force) {
      if (this.isSynced && force !== true) return;
      this._syncFromSource();
      this.isSynced = true;
      return;
    },

    refresh: function () {
      if (!this.allowRefresh) return false;
      this.disconnect();
      this._setup();
    },

    connect: function () {
      if (this.isConnected) return;
      this._connectSource();
      this._connectTarget();
      this.isConnected = true;
    },

    disconnect: function () {
      this._disconnectSource();
      this._disconnectTarget();
      this.isSynced = false;
      this.isConnected = false;
    },

    _disconnectSource: function () {
      var sp = this._sourceProperty, sc = this._sourceComputedProperty;
      if (!this._source) return;
      this._source.removeObserver(sc || sp, this._sourceResponder);
    },

    _disconnectTarget: function () {
      if (!this._target) return;
      this._target.removeObserver(this._targetProperty, this._targetResponder);
    },

    suspend: function () {

    },

    getTargetValue: function () {
      //var r = enyo.getPath.call(this._target, this._targetProperty);

      if (!this._target) {
        enyo.error("no target", this);
      }

      var r = this._target.get(this._targetProperty);
      if (r instanceof Object) r = copyTransform(r);
      return r;
    },

    setTargetValue: function (inValue) {
      var v = this.transform && enyo.isFunction(this.transform)? this.transform(inValue, "target"): inValue;
      this.isSynced = true;
      return this._target.set(this._targetProperty, v, enyo.isArray(v));
    },

    getSourceValue: function () {
      var r, sp = this._sourceProperty, sc = this._sourceComputedProperty;
      //if (sc) r = enyo.getPath.call(this._source, sc)[sp];
      //else r = enyo.getPath.call(this._source, this._sourceProperty);
      if (sc) r = this._source.get(sc)[sp];
      else r = this._source.get(this._sourceProperty);
      if (r instanceof Object) r = copyTransform(r);
      return r;
    },

    setSourceValue: function (inValue) {
      var v = this.transform && enyo.isFunction(this.transform)? this.transform(inValue, "source"): inValue;
      return this._source.set(this._sourceProperty, v);
    },

    destroy: function () {
      this.disconnect();
      this._source = null;
      this._target = null;
      this._sourceResponder = null;
      this._targetResponder = null;
      this.isDestroyed = true;
      enyo.bindingCount--;

      if (this.owner) {
        this.owner.removeBinding(this);
      }
      //console.log("REMOVED A BINDING: ", enyo.bindingCount);
    }
  };

}());
<|endoftext|>