<commit_before>/**
 * TweetFoil Core
 *
 * @fileoverview  Core variables and plugin object.
 * @link          https://github.com/stevenbenner/jquery-tweetfoil
 * @author        Steven Benner (http://stevenbenner.com/)
 * @requires      jQuery 1.7+
 */

// constants
var HOST = 'cdn.syndication.twimg.com',
	PATH = '/widgets/timelines/';

/**
 * Pull tweets from Twitter using the specified widgit id and display them
 * in an unordered list.
 * @param {Object} opts The options object to use for the plugin.
 * @return {jQuery} jQuery object for the matched selectors.
 */
$.fn.tweetFoil = function(opts) {
	var $this = this,
		options = $.extend({}, $.fn.tweetFoil.defaults, opts),
		list = $('

').addClass(options.className);

	// pull the data from the twitter api
	$.ajax({
		url: 'https://' + HOST + PATH + options.widgetId,
		data: {
			'dnt': 'true',
			'lang': 'en',
			'suppress_response_codes': 'true'
		},
		cache: false,
		type: 'GET',
		dataType: 'jsonp'
	}).done(function(response) {
		var rawTweets = $(response.body).find('.e-entry-title'),
			count = options.limit > rawTweets.length ? rawTweets.length : options.limit,
			i = 0;

		// add list items
		rawTweets.each(function() {
			list.append($('
').append(this));

			// break on limit
			if (++i >= count) {
				return false;
			}
		});

		$this.append(list);
	});

	return $this;
};

/**
 * Default options for the plugin.
 */
$.fn.tweetFoil.defaults = {
	widgetId: '348706263581995009',
	limit: 10,
	className: 'tweetFoil'
};
<commit_msg>Moved URL scheme to a variable.<commit_after>/**
 * TweetFoil Core
 *
 * @fileoverview  Core variables and plugin object.
 * @link          https://github.com/stevenbenner/jquery-tweetfoil
 * @author        Steven Benner (http://stevenbenner.com/)
 * @requires      jQuery 1.7+
 */

// constants
var SCHEME = 'https',
	HOST = 'cdn.syndication.twimg.com',
	PATH = '/widgets/timelines/';

/**
 * Pull tweets from Twitter using the specified widgit id and display them
 * in an unordered list.
 * @param {Object} opts The options object to use for the plugin.
 * @return {jQuery} jQuery object for the matched selectors.
 */
$.fn.tweetFoil = function(opts) {
	var $this = this,
		options = $.extend({}, $.fn.tweetFoil.defaults, opts),
		list = $('

').addClass(options.className);

	// pull the data from the twitter api
	$.ajax({
		url: SCHEME + '://' + HOST + PATH + options.widgetId,
		data: {
			'dnt': 'true',
			'lang': 'en',
			'suppress_response_codes': 'true'
		},
		cache: false,
		type: 'GET',
		dataType: 'jsonp'
	}).done(function(response) {
		var rawTweets = $(response.body).find('.e-entry-title'),
			count = options.limit > rawTweets.length ? rawTweets.length : options.limit,
			i = 0;

		// add list items
		rawTweets.each(function() {
			list.append($('
').append(this));

			// break on limit
			if (++i >= count) {
				return false;
			}
		});

		$this.append(list);
	});

	return $this;
};

/**
 * Default options for the plugin.
 */
$.fn.tweetFoil.defaults = {
	widgetId: '348706263581995009',
	limit: 10,
	className: 'tweetFoil'
};
<|endoftext|>


<commit_before>"use strict";
(function(window) {
    function Moon(opts) {
        var _el = opts.el;
        var _data = opts.data;
        var _methods = opts.methods;
        var directives = {};
        var self = this;
        this.$el = document.querySelector(_el);
        this.components = opts.components;
        this.dom = {type: this.$el.nodeName, children: [], node: this.$el};

        // Change state when $data is changed
        Object.defineProperty(this, '$data', {
            get: function() {
                return _data;
            },
            set: function(value) {
                _data = value;
                this.build(this.dom.children);
            }
        });

        /**
        * Converts attributes into key-value pairs
        * @param {Node} node
        * @return {Object} Key-Value pairs of Attributes
        */
        var extractAttrs = function(node) {
          var attrs = {};
          if(!node.attributes) return attrs;
          var rawAttrs = node.attributes;
          for(var i = 0; i < rawAttrs.length; i++) {
            attrs[rawAttrs[i].name] = rawAttrs[i].value
          }

          return attrs;
        }

        /**
        * Compiles a template with given data
        * @param {String} template
        * @param {Object} data
        * @return {String} Template with data rendered
        */
        var compileTemplate = function(template, data) {
          var code = template,
              re = /{{([A-Za-z0-9_.]+)}}/gi;
          code.replace(re, function(match, p) {
            code = code.replace(match, "` + data." + p + " + `");
          });
          var compile = new Function("data", "var out = `" + code + "`; return out");
          return compile(data);
        }

        /**
        * Creates an object to be used in a Virtual DOM
        * @param {String} type
        * @param {Array} children
        * @param {String} val
        * @param {Object} props
        * @param {Node} node
        * @return {Object} Object usable in Virtual DOM
        */
        this.createElement = function(type, children, val, props, node) {
          return {type: type, children: children, val: val, props: props, node: node};
        }

        /**
        * Create Elements Recursively For all Children
        * @param {Array} children
        * @return {Array} Array of elements usable in Virtual DOM
        */
        this.recursiveChildren = function(children) {
          var recursiveChildrenArr = [];
          for(var i = 0; i < children.length; i++) {
            var child = children[i];
            recursiveChildrenArr.push(this.createElement(child.nodeName, this.recursiveChildren(child.childNodes), child.textContent, extractAttrs(child), child));
          }
          return recursiveChildrenArr;
        }

        /**
        * Creates Virtual DOM
        * @param {Node} node
        */
        this.createVirtualDOM = function(node) {
          var vdom = this.createElement(node.nodeName, this.recursiveChildren(node.childNodes), node.textContent, extractAttrs(node), node);
          this.dom = vdom;
        }

        /**
        * Turns Custom Components into their Corresponding Templates
        */
        this.componentsToHTML = function() {
          for(var component in this.components) {
            var componentsFound = document.getElementsByTagName(component);
            componentsFound = Array.prototype.slice.call(componentsFound);
            for(var i = 0; i < componentsFound.length; i++) {
              var componentFound = componentsFound[i];
              var componentProps = extractAttrs(componentFound);
              var componentDummy = document.createElement('div');
              componentDummy.innerHTML = this.components[component].template;
              componentDummy = componentDummy.firstChild;

              for(var attr in componentProps) {
                componentDummy.setAttribute(attr, componentProps[attr]);
              }

              componentFound.outerHTML = componentDummy.outerHTML;
            }
          }
        }

        /**
        * Sets Value in Data
        * @param {String} key
        * @param {String} val
        */
        this.set = function(key, val) {
          this.$data[key] = val;
          this.build(this.dom.children);
        }

        /**
        * Gets Value in Data
        * @param {String} key
        * @return {String} Value of key in data
        */
        this.get = function(key) {
          return this.$data[key];
        }

        /**
        * Makes an AJAX Request
        * @param {String} method
        * @param {String} url
        * @param {Object} params
        * @param {Function} cb
        */
        this.ajax = function(method, url, params, cb) {
          var xmlHttp = new XMLHttpRequest();
          method = method.toUpperCase();
          if(typeof params === "function") {
            cb = params;
          }
          var urlParams = "?";
          if(method === "POST") {
            http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            for(var param in params) {
              urlParams += param + "=" + params[param] + "&";
            }
          }
          xmlHttp.onreadystatechange = function() {
          if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
            cb(JSON.parse(xmlHttp.responseText));
          }
          xmlHttp.open(method, url, true);
          xmlHttp.send(method === "POST" ? urlParams : null);
        }

        /**
        * Calls a method
        * @param {String} method
        */
        this.method = function(method) {
          _methods[method]();
        }

        // Directive Initialization
        this.directive = function(name, action) {
          directives["m-" + name] = action;
        }

        // Default Directives
        directives["m-if"] = function(el, val, vdom) {
          var evaluated = new Function("return " + val);
          if(!evaluated()) {
            el.textContent = "";
          } else {
            el.textContent = compileTemplate(vdom.val, self.$data);
          }
        }

        directives["m-on"] = function(el, val, vdom) {
          var splitVal = val.split(":");
          var eventToCall = splitVal[0];
          var methodToCall = splitVal[1];
          el.addEventListener(eventToCall, function() {
            self.method(methodToCall);
          });
          el.removeAttribute("m-on");
          delete vdom.props["m-on"];
        }

        directives["m-model"] = function(el, val, vdom) {
          el.value = self.get(val);
          el.addEventListener("input", function() {
            self.set(val, el.value);
          });
          el.removeAttribute("m-model");
          delete vdom.props["m-model"];
        }

        directives["m-for"] = function(el, val, vdom) {
          var splitVal = val.split(" in ");
          var alias = splitVal[0];
          var arr = self.get(splitVal[1]);
          var compilable = vdom.val.replace(new RegExp(alias, "gi"), splitVal[1]);
          el.innerHTML = compilable;
          for(var i = 1; i < arr.length; i++) {
            var clone = el.cloneNode(true);
            var parent = el.parentNode;
            parent.appendChild(clone);
          }
        }

        /**
        * Builds the DOM With Data
        * @param {Array} children
        */
        this.build = function(children) {
          for(var i = 0; i < children.length; i++) {
            var el = children[i];

            if(el.type === "#text") {
              el.node.textContent = compileTemplate(el.val, this.$data);
            } else if(el.props) {
              for(var prop in el.props) {
                var propVal = el.props[prop];
                var compiledProperty = compileTemplate(propVal, this.$data);
                var directive = directives[prop];
                if(directive) {
                  directive(el.node, compiledProperty, el);
                }

                el.node.setAttribute(prop, compiledProperty);
              }
            }

            this.build(el.children);
          }
        }

        // Initialize 🎉
        this.componentsToHTML();
        this.createVirtualDOM(this.$el);
        this.build(this.dom.children);
    }

    window.Moon = Moon;
    window.$ = function(el) {
      el = document.querySelectorAll(el);
      return el.length === 1 ? el[0] : el;
    }

})(window);
<commit_msg>directive set value<commit_after>"use strict";
(function(window) {
    function Moon(opts) {
        var _el = opts.el;
        var _data = opts.data;
        var _methods = opts.methods;
        var directives = {};
        var self = this;
        this.$el = document.querySelector(_el);
        this.components = opts.components;
        this.dom = {type: this.$el.nodeName, children: [], node: this.$el};

        // Change state when $data is changed
        Object.defineProperty(this, '$data', {
            get: function() {
                return _data;
            },
            set: function(value) {
                _data = value;
                this.build(this.dom.children);
            }
        });

        /**
        * Converts attributes into key-value pairs
        * @param {Node} node
        * @return {Object} Key-Value pairs of Attributes
        */
        var extractAttrs = function(node) {
          var attrs = {};
          if(!node.attributes) return attrs;
          var rawAttrs = node.attributes;
          for(var i = 0; i < rawAttrs.length; i++) {
            attrs[rawAttrs[i].name] = rawAttrs[i].value
          }

          return attrs;
        }

        /**
        * Compiles a template with given data
        * @param {String} template
        * @param {Object} data
        * @return {String} Template with data rendered
        */
        var compileTemplate = function(template, data) {
          var code = template,
              re = /{{([A-Za-z0-9_.]+)}}/gi;
          code.replace(re, function(match, p) {
            code = code.replace(match, "` + data." + p + " + `");
          });
          var compile = new Function("data", "var out = `" + code + "`; return out");
          return compile(data);
        }

        /**
        * Creates an object to be used in a Virtual DOM
        * @param {String} type
        * @param {Array} children
        * @param {String} val
        * @param {Object} props
        * @param {Node} node
        * @return {Object} Object usable in Virtual DOM
        */
        this.createElement = function(type, children, val, props, node) {
          return {type: type, children: children, val: val, props: props, node: node};
        }

        /**
        * Create Elements Recursively For all Children
        * @param {Array} children
        * @return {Array} Array of elements usable in Virtual DOM
        */
        this.recursiveChildren = function(children) {
          var recursiveChildrenArr = [];
          for(var i = 0; i < children.length; i++) {
            var child = children[i];
            recursiveChildrenArr.push(this.createElement(child.nodeName, this.recursiveChildren(child.childNodes), child.textContent, extractAttrs(child), child));
          }
          return recursiveChildrenArr;
        }

        /**
        * Creates Virtual DOM
        * @param {Node} node
        */
        this.createVirtualDOM = function(node) {
          var vdom = this.createElement(node.nodeName, this.recursiveChildren(node.childNodes), node.textContent, extractAttrs(node), node);
          this.dom = vdom;
        }

        /**
        * Turns Custom Components into their Corresponding Templates
        */
        this.componentsToHTML = function() {
          for(var component in this.components) {
            var componentsFound = document.getElementsByTagName(component);
            componentsFound = Array.prototype.slice.call(componentsFound);
            for(var i = 0; i < componentsFound.length; i++) {
              var componentFound = componentsFound[i];
              var componentProps = extractAttrs(componentFound);
              var componentDummy = document.createElement('div');
              componentDummy.innerHTML = this.components[component].template;
              componentDummy = componentDummy.firstChild;

              for(var attr in componentProps) {
                componentDummy.setAttribute(attr, componentProps[attr]);
              }

              componentFound.outerHTML = componentDummy.outerHTML;
            }
          }
        }

        /**
        * Sets Value in Data
        * @param {String} key
        * @param {String} val
        */
        this.set = function(key, val) {
          this.$data[key] = val;
          this.build(this.dom.children);
        }

        /**
        * Gets Value in Data
        * @param {String} key
        * @return {String} Value of key in data
        */
        this.get = function(key) {
          return this.$data[key];
        }

        /**
        * Makes an AJAX Request
        * @param {String} method
        * @param {String} url
        * @param {Object} params
        * @param {Function} cb
        */
        this.ajax = function(method, url, params, cb) {
          var xmlHttp = new XMLHttpRequest();
          method = method.toUpperCase();
          if(typeof params === "function") {
            cb = params;
          }
          var urlParams = "?";
          if(method === "POST") {
            http.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            for(var param in params) {
              urlParams += param + "=" + params[param] + "&";
            }
          }
          xmlHttp.onreadystatechange = function() {
          if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
            cb(JSON.parse(xmlHttp.responseText));
          }
          xmlHttp.open(method, url, true);
          xmlHttp.send(method === "POST" ? urlParams : null);
        }

        /**
        * Calls a method
        * @param {String} method
        */
        this.method = function(method) {
          _methods[method]();
        }

        // Directive Initialization
        this.directive = function(name, action) {
          directives["m-" + name] = action;
        }

        // Default Directives
        directives["m-if"] = function(el, val, vdom) {
          var evaluated = new Function("return " + val);
          if(!evaluated()) {
            el.textContent = "";
          } else {
            el.textContent = compileTemplate(vdom.val, self.$data);
          }
        }

        directives["m-on"] = function(el, val, vdom) {
          var splitVal = val.split(":");
          var eventToCall = splitVal[0];
          var methodToCall = splitVal[1];
          el.addEventListener(eventToCall, function() {
            self.method(methodToCall);
          });
          el.removeAttribute("m-on");
          delete vdom.props["m-on"];
        }

        directives["m-model"] = function(el, val, vdom) {
          el.value = self.get(val);
          el.addEventListener("input", function() {
            self.set(val, el.value);
          });
          el.removeAttribute("m-model");
          delete vdom.props["m-model"];
        }

        directives["m-for"] = function(el, val, vdom) {
          var splitVal = val.split(" in ");
          var alias = splitVal[0];
          var arr = self.get(splitVal[1]);
          var compilable = vdom.val.replace(new RegExp(alias, "gi"), splitVal[1] + '[Moon_For_Directive_Set_Value]');
          el.innerHTML = compilable;
          for(var i = 1; i < arr.length; i++) {
            var clone = el.cloneNode(true);
            var parent = el.parentNode;
            parent.appendChild(clone);
          }
        }

        /**
        * Builds the DOM With Data
        * @param {Array} children
        */
        this.build = function(children) {
          for(var i = 0; i < children.length; i++) {
            var el = children[i];

            if(el.type === "#text") {
              el.node.textContent = compileTemplate(el.val, this.$data);
            } else if(el.props) {
              for(var prop in el.props) {
                var propVal = el.props[prop];
                var compiledProperty = compileTemplate(propVal, this.$data);
                var directive = directives[prop];
                if(directive) {
                  directive(el.node, compiledProperty, el);
                }

                el.node.setAttribute(prop, compiledProperty);
              }
            }

            this.build(el.children);
          }
        }

        // Initialize 🎉
        this.componentsToHTML();
        this.createVirtualDOM(this.$el);
        this.build(this.dom.children);
    }

    window.Moon = Moon;
    window.$ = function(el) {
      el = document.querySelectorAll(el);
      return el.length === 1 ? el[0] : el;
    }

})(window);
<|endoftext|>


<commit_before>GRUNT = (function() {
    // define the GRUNT module
    var module = {
        id: "grunt.core",

        /*
        Very gr*nty jQuery stuff.
        Taken from http://github.com/jquery/jquery/blob/master/src/core.js
        */

        extend: function() {
            // copy reference to target object
            var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;

            // Handle a deep copy situation
            if ( typeof target === "boolean" ) {
                deep = target;
                target = arguments[1] || {};
                // skip the boolean and the target
                i = 2;
            }

            // Handle case when target is a string or something (possible in deep copy)
            if ( typeof target !== "object" && !module.isFunction(target) ) {
                target = {};
            }

            // extend module itself if only one argument is passed
            if ( length === i ) {
                target = this;
                --i;
            }

            for ( ; i < length; i++ ) {
                // Only deal with non-null/undefined values
                if ( (options = arguments[ i ]) != null ) {
                    // Extend the base object
                    for ( name in options ) {
                        src = target[ name ];
                        copy = options[ name ];

                        // Prevent never-ending loop
                        if ( target === copy ) {
                            continue;
                        }

                        // Recurse if we're merging object literal values or arrays
                        if ( deep && copy && ( module.isPlainObject(copy) || module.isArray(copy) ) ) {
                            var clone = src && ( module.isPlainObject(src) || module.isArray(src) ) ? src
                                : module.isArray(copy) ? [] : {};

                            // Never move original objects, clone them
                            target[ name ] = module.extend( deep, clone, copy );

                        // Don't bring in undefined values
                        } else if ( copy !== undefined ) {
                            target[ name ] = copy;
                        }
                    }
                }
            }

            // Return the modified object
            return target;
        },

        isFunction: function( obj ) {
            return toString.call(obj) === "[object Function]";
        },

        isArray: function( obj ) {
            return toString.call(obj) === "[object Array]";
        },

        isPlainObject: function( obj ) {
            // Must be an Object.
            // Because of IE, we also have to check the presence of the constructor property.
            // Make sure that DOM nodes and window objects don't pass through, as well
            if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {
                return false;
            }

            // Not own constructor property must be Object
            if ( obj.constructor &&
                !hasOwn.call(obj, "constructor") &&
                !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
                return false;
            }

            // Own properties are enumerated firstly, so to speed up,
            // if last one is own, then all properties are own.

            var key;
            for ( key in obj ) {}

            return key === undefined || hasOwn.call( obj, key );
        },

        isEmptyObject: function( obj ) {
            for ( var name in obj ) {
                return false;
            }
            return true;
        },

        isXmlDocument: function(obj) {
            return toString.call(obj) === "[object Document]";
        }
    }; // module definition

    return module;
})();

<commit_msg>Added missing hasOwn variable used in jQuery isPlainObject<commit_after>GRUNT = (function() {
    var hasOwn = Object.prototype.hasOwnProperty;

    // define the GRUNT module
    var module = {
        id: "grunt.core",

        /*
        Very gr*nty jQuery stuff.
        Taken from http://github.com/jquery/jquery/blob/master/src/core.js
        */

        extend: function() {
            // copy reference to target object
            var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options, name, src, copy;

            // Handle a deep copy situation
            if ( typeof target === "boolean" ) {
                deep = target;
                target = arguments[1] || {};
                // skip the boolean and the target
                i = 2;
            }

            // Handle case when target is a string or something (possible in deep copy)
            if ( typeof target !== "object" && !module.isFunction(target) ) {
                target = {};
            }

            // extend module itself if only one argument is passed
            if ( length === i ) {
                target = this;
                --i;
            }

            for ( ; i < length; i++ ) {
                // Only deal with non-null/undefined values
                if ( (options = arguments[ i ]) != null ) {
                    // Extend the base object
                    for ( name in options ) {
                        src = target[ name ];
                        copy = options[ name ];

                        // Prevent never-ending loop
                        if ( target === copy ) {
                            continue;
                        }

                        // Recurse if we're merging object literal values or arrays
                        if ( deep && copy && ( module.isPlainObject(copy) || module.isArray(copy) ) ) {
                            var clone = src && ( module.isPlainObject(src) || module.isArray(src) ) ? src
                                : module.isArray(copy) ? [] : {};

                            // Never move original objects, clone them
                            target[ name ] = module.extend( deep, clone, copy );

                        // Don't bring in undefined values
                        } else if ( copy !== undefined ) {
                            target[ name ] = copy;
                        }
                    }
                }
            }

            // Return the modified object
            return target;
        },

        isFunction: function( obj ) {
            return toString.call(obj) === "[object Function]";
        },

        isArray: function( obj ) {
            return toString.call(obj) === "[object Array]";
        },

        isPlainObject: function( obj ) {
            // Must be an Object.
            // Because of IE, we also have to check the presence of the constructor property.
            // Make sure that DOM nodes and window objects don't pass through, as well
            if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {
                return false;
            }

            // Not own constructor property must be Object
            if ( obj.constructor &&
                !hasOwn.call(obj, "constructor") &&
                !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
                return false;
            }

            // Own properties are enumerated firstly, so to speed up,
            // if last one is own, then all properties are own.

            var key;
            for ( key in obj ) {}

            return key === undefined || hasOwn.call( obj, key );
        },

        isEmptyObject: function( obj ) {
            for ( var name in obj ) {
                return false;
            }
            return true;
        },

        isXmlDocument: function(obj) {
            return toString.call(obj) === "[object Document]";
        }
    }; // module definition

    return module;
})();

<|endoftext|>


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

"use strict";

/**
 * @param {Function} parentClass
 * @returns {Function} The instance on which this method was called.
 */
Function.prototype.inherit = function inherit(parentClass) {
    this.prototype = Object.create(parentClass.prototype);
    this.prototype.constructor = this;

    // TODO: think a better way to get the parent class.
    this.prototype.parentClass = parentClass;

    return this;
};

/**
 * @param {String} memberName
 * @param {Function} memberMethod
 * @returns {Function} The instance on which this method was called.
 */
Function.prototype.member = function member(memberName, memberMethod) {
    this.prototype[memberName] = memberMethod;

    return this;
};

/**
 * @namespace
 */
var utils = {

    /**
     * @param {Object} sourceObject
     * @param {Boolean} recursiveCall
     * @returns {Object} The new object cloned.
     */
    cloneObject: function cloneObject(sourceObject, recursiveCall) {
        var cloned, i;

        if (typeof recursiveCall !== 'boolean') {
            recursiveCall = false;
        }

        if (sourceObject == null || typeof sourceObject !== 'object') {
            return recursiveCall ? sourceObject : {};
        }

        if (sourceObject instanceof RegExp) {
            return sourceObject;
        }

        if (Array.isArray(sourceObject)) {
            cloned = [];
        } else {
            cloned = {};
        }

        for (i in sourceObject) {
            if (sourceObject[i] != null && typeof sourceObject[i] === 'object') {
                cloned[i] = this.cloneObject(sourceObject[i], true);
            } else {
                cloned[i] = sourceObject[i];
            }
        }

        return cloned;
    },

    /**
     * @param {String} sourceString
     * @param {Object.<String, *>} namedArgs
     * @returns {String} The new string formatted.
     */
    formatString: function formatString(sourceString, namedArgs) {
        var name;

        for (name in namedArgs) {
            if (sourceString.indexOf("%(" + name + ")s") != -1) {
                sourceString = sourceString.replace("%(" + name + ")s", namedArgs[name]);
            }
        }

        return sourceString;
    },

    /**
     * @param {Object} sourceObject
     * @param {Object} targetObject
     * @return {Object} The sourceObject merged with targetObject.
     */
    updateObject: function updateObject(sourceObject, targetObject) {
        var name;

        sourceObject = this.cloneObject(sourceObject);
        targetObject = this.cloneObject(targetObject);

        for (name in sourceObject) {
            if (name in targetObject) {
                sourceObject[name] = targetObject[name];
            }
        }

        return sourceObject;
    }

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

"use strict";

/**
 * @param {Function} parentClass
 * @returns {Function} The instance on which this method was called.
 */
Function.prototype.inherit = function inherit(parentClass) {
    var callCounter = 0;

    this.prototype = Object.create(parentClass.prototype);
    this.prototype.constructor = this;
    this.prototype.parentClass = parentClass;

    this.prototype.callParent = function callParent() {
        var currentClass, i;

        currentClass = parentClass;

        for (i = 0; i < callCounter; i++) {
            currentClass = currentClass.prototype.parentClass;
        }

        callCounter++;
        currentClass.apply(this, Array.prototype.slice.call(arguments));
        callCounter--;

        return this;
    };

    return this;
};

/**
 * @param {String} memberName
 * @param {Function} memberMethod
 * @returns {Function} The instance on which this method was called.
 */
Function.prototype.member = function member(memberName, memberMethod) {
    this.prototype[memberName] = memberMethod;

    return this;
};

/**
 * @namespace
 */
var utils = {

    /**
     * @param {Object} sourceObject
     * @param {Boolean} recursiveCall
     * @returns {Object} The new object cloned.
     */
    cloneObject: function cloneObject(sourceObject, recursiveCall) {
        var cloned, i;

        if (typeof recursiveCall !== 'boolean') {
            recursiveCall = false;
        }

        if (sourceObject == null || typeof sourceObject !== 'object') {
            return recursiveCall ? sourceObject : {};
        }

        if (sourceObject instanceof RegExp) {
            return sourceObject;
        }

        if (Array.isArray(sourceObject)) {
            cloned = [];
        } else {
            cloned = {};
        }

        for (i in sourceObject) {
            if (sourceObject[i] != null && typeof sourceObject[i] === 'object') {
                cloned[i] = this.cloneObject(sourceObject[i], true);
            } else {
                cloned[i] = sourceObject[i];
            }
        }

        return cloned;
    },

    /**
     * @param {String} sourceString
     * @param {Object.<String, *>} namedArgs
     * @returns {String} The new string formatted.
     */
    formatString: function formatString(sourceString, namedArgs) {
        var name;

        for (name in namedArgs) {
            if (sourceString.indexOf("%(" + name + ")s") != -1) {
                sourceString = sourceString.replace("%(" + name + ")s", namedArgs[name]);
            }
        }

        return sourceString;
    },

    /**
     * @param {Object} sourceObject
     * @param {Object} targetObject
     * @return {Object} The sourceObject merged with targetObject.
     */
    updateObject: function updateObject(sourceObject, targetObject) {
        var name;

        sourceObject = this.cloneObject(sourceObject);
        targetObject = this.cloneObject(targetObject);

        for (name in sourceObject) {
            if (name in targetObject) {
                sourceObject[name] = targetObject[name];
            }
        }

        return sourceObject;
    }

};
<|endoftext|>


<commit_before>(function(global) {
    var handlersRepo = [], listenersRepo = [], aggregatesRepo = [], counter = 0;

    // handlers' repo functions
    function addHandler(owner, commandName, callback) {
    }

    function removeHandlers(owner) {
    }

    function getHandler(commandName) {
    }

    // listeners' repo functions
    function addListener(owner, eventName, callback) {
    }

    function removeListeners(owner) {
    }

    function listListeners(eventName) {
    }

    // aggregates listeners' repo functions
    function addAggregateListener(owner, aggregateName, eventName, callback) {
    }

    function removeAggregateListener(owner) {
    }

    function listAggregateListeners(aggregateName) {
    }

    // generate technical name for aggregate, command and event
    function generateTechnicalName(namespace, type, name) {
        if (namespace) {
            return [namespace, type, name].join('-');
        }
        return [type, name].join('-');
    }

    // cqrs implementation
    function cqrs(callback, params) {
        var cqrsCb, owner, namespace, exports;
        exports = {};
        cqrsCb = callback;
        owner = (params && params.owner) || ('owner-' + (counter++));
        namespace = params && params.namespace;

        // to handle a command
        function handle(commandName, callback) {
            var cmdName = generateTechnicalName(namespace, 'cmd', commandName);
            if (!getHandler(cmdName)) {
                addHandler(owner, cmdName, callback);
            }
            return exports;
        }
        exports.handle = handle;

        // to send a command
        function send(commandName, payload, metadata) {
            var cmdName = generateTechnicalName(namespace, 'cmd', commandName);
        }
        exports.send = send;

        // to listen an event
        function listen(eventName, callback) {
            var evtName = generateTechnicalName(namespace, 'evt', commandName);
            addListener(owner, evtName, callback);
            return exports;
        }
        exports.listen = listen;

        // to publish an event
        function publish(eventName, payload, metadata) {
            var evtName = generateTechnicalName(namespace, 'evt', commandName);
        }
        exports.publish = publish;

        // to register an aggregate
        function aggregate(aggregateName, payload, metadata) {
            var aggName = generateTechnicalName(namespace, 'agg', commandName);

            // to publish an event from an aggregate
            function apply(eventName, payload, metadata) {
                var evtName = generateTechnicalName(namespace, 'evt', commandName);
            }

            // to handle a command from an aggregate
            function aggregateHandler(commandName, callback) {
                var cmdName = generateTechnicalName(namespace, 'cmd', commandName);
            }

            // to listen an event from an aggregate
            function aggregateListener(eventName, callback) {
                var evtName = generateTechnicalName(namespace, 'evt', commandName);
            }

            return {
                handle: aggregateHandler,
                listen: aggregateListener
            };
        }
        exports.aggregate = aggregate;

        // to safely destroy the cqrs instance
        function destroy() {
        }
        exports.destroy = destroy;

        return exports;
    }

    return cqrs;
}(this));<commit_msg>begin implementation<commit_after>(function(global) {
    var handlersRepo = [], listenersRepo = [], aggregatesRepo = [], counter = 0;

    // handlers' repo functions
    function addHandler(owner, commandName, callback) {
        var alreadyRegistered = handlersRepo.some(function (e) {
            return e.commandName === commandName;
        });
        if (!alreadyRegistered) {
            handlersRepo.push({
                owner: owner,
                commandName: commandName,
                callback: callback
            });
        }
    }

    function removeHandlers(owner) {
        var commands = handlersRepo.filter(function (e) {
            return e.owner === owner;
        });
        commands.forEach(function (e) {
            handlersRepo.splice(e, 1);
        });
    }

    function getHandler(commandName) {
        var commands = handlersRepo.filter(function (e) {
            return e.commandName === commandName;
        });
        if (commands.length > 0) {
            return commands[0];
        }
    }

    // listeners' repo functions
    function addListener(owner, eventName, callback) {
        eventsRepo.push({
            owner: owner,
            eventName: eventName,
            callback: callback
        });
    }

    function removeListeners(owner) {
        var events = eventsRepo.filter(function (e) {
            return e.owner === owner;
        });
        events.forEach(function (e) {
            eventsRepo.splice(e, 1);
        });
    }

    function listListeners(eventName) {
        return eventsRepo.filter(function (e) {
            return e.eventName === eventName;
        });
    }

    // aggregates listeners' repo functions
    function addAggregateListener(owner, aggregateName, eventName, callback) {
        var aggregates = aggregatesRepo.filter(function (e) {
            return e.owner === owner && e.aggregateName === aggregateName;
        });
        if (aggregates.length > 0) {
            aggregate = aggregates[0];
        } else {
            aggregate = {
                owner: owner,
                aggregateName: aggregateName
                listeners: []
            };
        }
        aggregate.listeners.push({
            eventName: eventName,
            callback: callback
        });
    }

    function removeAggregateListener(owner) {
        var aggregates = aggregatesRepo.filter(function (e) {
            return e.owner === owner;
        });
        aggregates.forEach(function (e) {
            aggregatesRepo.splice(e, 1);
        });
    }

    function listAggregateListeners(aggregateName) {
        return aggregatesRepo.filter(function (e) {
            return e.aggregateName === aggregateName;
        }).map(function (e) {
            return e.listeners;
        }).reduce(function (a, b) {
            return a.concate(b)
        }, []);
    }

    // generate technical name for aggregate, command and event
    function generateTechnicalName(namespace, type, name) {
        if (namespace) {
            return [namespace, type, name].join('-');
        }
        return [type, name].join('-');
    }

    // cqrs implementation
    function cqrs(callback, params) {
        var cqrsCb, owner, namespace, exports;
        exports = {};
        cqrsCb = callback;
        owner = (params && params.owner) || ('owner-' + (counter++));
        namespace = params && params.namespace;

        // to handle a command
        function handle(commandName, callback) {
            var cmdName = generateTechnicalName(namespace, 'cmd', commandName);
            if (!getHandler(cmdName)) {
                addHandler(owner, cmdName, callback);
            }
            return exports;
        }
        exports.handle = handle;

        // to send a command
        function send(commandName, payload, metadata) {
            return new Promise(function (resolve, reject) {
                var cmdName = generateTechnicalName(namespace, 'cmd', commandName);

            });
        }
        exports.send = send;

        // to listen an event
        function listen(eventName, callback) {
            var evtName = generateTechnicalName(namespace, 'evt', commandName);
            addListener(owner, evtName, callback);
            return exports;
        }
        exports.listen = listen;

        // to publish an event
        function publish(eventName, payload, metadata) {
            return new Promise(function (resolve, reject) {
                var evtName = generateTechnicalName(namespace, 'evt', commandName);
            });
        }
        exports.publish = publish;

        // to register an aggregate
        function aggregate(aggregateName, payload, metadata) {
            var aggName = generateTechnicalName(namespace, 'agg', commandName);
            var exports = {};

            // to publish an event from an aggregate
            function apply(eventName, payload, metadata) {
                return new Promise(function (resolve, reject) {
                    var evtName = generateTechnicalName(namespace, 'evt', commandName);
                });
            }

            // to handle a command from an aggregate
            function aggregateHandler(commandName, callback) {
                var cmdName = generateTechnicalName(namespace, 'cmd', commandName);

            }
            exports.handle = aggregateHandler;

            // to listen an event from an aggregate
            function aggregateListener(eventName, callback) {
                var evtName = generateTechnicalName(namespace, 'evt', commandName);
            }
            exports.listen = aggregateListener;

            return exports;
        }
        exports.aggregate = aggregate;

        // to safely destroy the cqrs instance
        function destroy() {
        }
        exports.destroy = destroy;

        return exports;
    }

    function setDefaultRepos(defaultHandlers, defaultListeners, defaultAggregates) {
        handlersRepo = defaultHandlers;
        listenersRepo = defaultListeners;
        aggregatesRepo = defaultAggregates;
    };
    cqrs.setDefaultRepos = setDefaultRepos;

    global.cqrs = cqrs;
}(this));
<|endoftext|>


<commit_before>'use strict'

const fetch = require('isomorphic-fetch')
const groupBy = require('lodash.groupBy')

const endpoint = 'http://199.217.112.113:8080/picture/picture'
const filters = ['decade', 'color', 'subject', 'view', 'collection', 'location']

const clean = (data) => ({
	  id:         data.id
	, url:        data.Bildname
	, thumb: {
		  url:    data.BildSmall
		, width:  data.width
		, height: data.height
	}
	, decade:     ((data.Decade - data.Decade % 10) || '?').toString()
	, collection: data.Collection
	, color:      data.Color.toLowerCase()
	, location:   data.Location
	, subject: 	  data.Subject
	, view:       data.View
})

const err = (e) => {throw e}

const data = fetch(endpoint)
.then((res) => res.json(), err)
.then((photos) => {
	photos = photos.map(clean)

	const data = {}
	for (let filter of filters)
		data[filter] = groupBy(photos, (p) => p[filter])

	return data
}, err)

module.exports = data
<commit_msg>fix tests :white_check_mark:<commit_after>'use strict'

const fetch = require('isomorphic-fetch')
const groupBy = require('lodash.groupby')

const endpoint = 'http://199.217.112.113:8080/picture/picture'
const filters = ['decade', 'color', 'subject', 'view', 'collection', 'location']

const clean = (data) => ({
	  id:         data.id
	, url:        data.Bildname
	, thumb: {
		  url:    data.BildSmall
		, width:  data.width
		, height: data.height
	}
	, decade:     ((data.Decade - data.Decade % 10) || '?').toString()
	, collection: data.Collection
	, color:      data.Color.toLowerCase()
	, location:   data.Location
	, subject: 	  data.Subject
	, view:       data.View
})

const err = (e) => {throw e}

const data = fetch(endpoint)
.then((res) => res.json(), err)
.then((photos) => {
	photos = photos.map(clean)

	const data = {}
	for (let filter of filters)
		data[filter] = groupBy(photos, (p) => p[filter])

	return data
}, err)

module.exports = data
<|endoftext|>


<commit_before>const Plugin = require('./plugin')

module.exports = class Drag extends Plugin
{
    constructor(parent)
    {
        super(parent)
        this.moved = false
    }

    down(x, y, data)
    {
        if (this.paused)
        {
            return
        }

        const pointers = data.input.pointers
        if (pointers.length === 1)
        {
            this.last = { x, y }
        }
    }

    move(x, y, data)
    {
        if (this.paused)
        {
            return
        }

        if (!this.last)
        {
            this.last = { x, y }
        }
        else
        {
            const pointers = data.input.pointers
            if (pointers.length === 1 || (pointers.length > 1 && !this.parent.plugin('pinch')))
            {
                const distX = x - this.last.x
                const distY = y - this.last.y
                if (this.moved || (this.parent.checkThreshold(distX) || this.parent.checkThreshold(distY)))
                {
                    this.parent.container.x += distX
                    this.parent.container.y += distY
                    this.last = { x, y }
                    if (!this.moved)
                    {
                        this.parent.emit('drag-start', this.parent)
                    }
                    this.moved = true
                }
            }
            else
            {
                this.moved = false
            }
        }
    }

    up()
    {
        if (this.last)
        {
            this.parent.emit('drag-end', this.parent)
            this.last = null
            this.moved = false
        }
    }

    resume()
    {
        this.last = null
        this.paused = false
    }
}<commit_msg>fixed drag event<commit_after>const Plugin = require('./plugin')

module.exports = class Drag extends Plugin
{
    constructor(parent)
    {
        super(parent)
        this.moved = false
    }

    down(x, y, data)
    {
        if (this.paused)
        {
            return
        }

        const pointers = data.input.pointers
        if (pointers.length === 1)
        {
            this.last = { x, y }
        }
    }

    move(x, y, data)
    {
        if (this.paused)
        {
            return
        }

        if (this.last)
        {
            const pointers = data.input.pointers
            if (pointers.length === 1 || (pointers.length > 1 && !this.parent.plugin('pinch')))
            {
                const distX = x - this.last.x
                const distY = y - this.last.y
                if (this.moved || (this.parent.checkThreshold(distX) || this.parent.checkThreshold(distY)))
                {
                    this.parent.container.x += distX
                    this.parent.container.y += distY
                    this.last = { x, y }
                    if (!this.moved)
                    {
                        this.parent.emit('drag-start', this.parent)
                    }
                    this.moved = true
                }
            }
            else
            {
                this.moved = false
            }
        }
    }

    up()
    {
        if (this.last)
        {
            this.parent.emit('drag-end', this.parent)
            this.last = null
            this.moved = false
        }
    }

    resume()
    {
        this.last = null
        this.paused = false
    }
}<|endoftext|>


<commit_before>import constant from "./constant";
import noop from "./noop";
import {event, customEvent, select, mouse, touch} from "d3-selection";

function nodefault() {
  event.preventDefault();
}

// Ignore right-click, since that should open the context menu.
// Ignore multiple starting touches on the same element.
function defaultFilter() {
  return event.identifier == null
      ? !event.sourceEvent.button
      : event.sourceEvent.changedTouches[0].identifier === event.identifier;
}

function defaultContainer() {
  return this.parentNode;
}

// Listen to the window for mousemove and mouseup such that we continue to
// receive events if the mouse goes outside the window.
function mouseContext() {
  return event.view;
}

// Listen to the event target for touchmove, touchend and touchcancel.
function touchContext() {
  return event.target;
}

export default function(dragstarted) {
  var filter = defaultFilter,
      container = defaultContainer,
      mousestart = start("mousemove", "mouseup", mouse, mouseContext),
      touchstart = start("touchmove", "touchend touchcancel", touch, touchContext);

  function drag(selection) {
    selection
        .on("mousedown.drag", mousedowned)
        .on("touchstart.drag", touchstarted);
  }

  function mousedowned() {
    mousestart(this, arguments);
  }

  function touchstarted() {
    for (var touches = event.changedTouches, i = 0, n = touches.length; i < n; ++i) {
      touchstart(this, arguments, touches[i].identifier);
    }
  }

  function start(move, end, position, contextify) {
    return function(that, args, id) {
      if (!customEvent({type: "beforedragstart", identifier: id}, function() {
        if (filter.apply(that, args)) {
          parent = container.apply(that, args);
          return true;
        }
      })) return;

      var parent,
          point = position(parent, id),
          listen = customEvent({type: "dragstart", identifier: id, x: point[0], y: point[1]}, dragstarted, that, args) || noop,
          dragged = typeof listen === "function" ? listen : listen.drag || noop,
          dragended = listen.dragend || noop,
          noclick = false,
          view = select(event.view).on(name("dragstart selectstart"), nodefault, true),
          context = select(contextify.apply(that, args)).on(name(move), moved).on(name(end), ended);

      // I’d like to call preventDefault on mousedown to disable native dragging
      // of links or images and native text selection. However, in Chrome this
      // causes mousemove and mouseup events outside an iframe to be dropped:
      // https://bugs.chromium.org/p/chromium/issues/detail?id=269917
      // And if you preventDefault on touchstart on iOS, it prevents the click
      // event on touchend, even if there was no touchmove! So instead, we
      // cancel the specific undesirable behaviors.

      function name(types) {
        var name = id == null ? ".drag" : ".drag-" + id;
        return types == null ? name : types.trim()
            .split(/^|\s+/)
            .map(function(type) { return type + name; })
            .join(" ");
      }

      function moved() {
        var p = position(parent, id);
        if (p == null) return; // This touch didn’t change.
        nodefault(), noclick = true;
        dragged.call(that, p[0], p[1], id);
      }

      function ended() {
        var p = position(parent, id);
        if (p == null) return; // This touch didn’t end.
        view.on(name(), null);
        context.on(name(), null);
        if (noclick) view.on(name("click"), nodefault, true), setTimeout(afterended, 0);
        dragended.call(that, p[0], p[1], id);
      }

      function afterended() {
        view.on(name("click"), null);
      }
    };
  }

  drag.filter = function(_) {
    return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), drag) : filter;
  };

  drag.container = function(_) {
    return arguments.length ? (container = typeof _ === "function" ? _ : constant(_), drag) : container;
  };

  return drag;
}
<commit_msg>Restore drag.{x,y}.<commit_after>import constant from "./constant";
import noop from "./noop";
import {event, customEvent, select, mouse, touch} from "d3-selection";

function nodefault() {
  event.preventDefault();
}

// Ignore right-click, since that should open the context menu.
// Ignore multiple starting touches on the same element.
function defaultFilter() {
  return event.identifier == null
      ? !event.sourceEvent.button
      : event.sourceEvent.changedTouches[0].identifier === event.identifier;
}

function defaultContainer() {
  return this.parentNode;
}

// Listen to the window for mousemove and mouseup such that we continue to
// receive events if the mouse goes outside the window.
function mouseContext() {
  return event.view;
}

// Listen to the event target for touchmove, touchend and touchcancel.
function touchContext() {
  return event.target;
}

export default function(dragstarted) {
  var x = null,
      y = null,
      filter = defaultFilter,
      container = defaultContainer,
      mousestart = start("mousemove", "mouseup", mouse, mouseContext),
      touchstart = start("touchmove", "touchend touchcancel", touch, touchContext);

  function drag(selection) {
    selection
        .on("mousedown.drag", mousedowned)
        .on("touchstart.drag", touchstarted);
  }

  function mousedowned() {
    mousestart(this, arguments);
  }

  function touchstarted() {
    for (var touches = event.changedTouches, i = 0, n = touches.length; i < n; ++i) {
      touchstart(this, arguments, touches[i].identifier);
    }
  }

  function start(move, end, position, contextify) {
    return function(that, args, id) {
      if (!customEvent({type: "beforedragstart", identifier: id}, function() {
        if (filter.apply(that, args)) {
          parent = container.apply(that, args);
          p0 = position(parent, id);
          dx = x == null ? 0 : x.apply(that, args) - p0[0];
          dy = y == null ? 0 : y.apply(that, args) - p0[1];
          return true;
        }
      })) return;

      var parent,
          p0,
          dx,
          dy,
          listen = customEvent({type: "dragstart", identifier: id, x: p0[0], y: p0[1]}, dragstarted, that, args) || noop,
          dragged = typeof listen === "function" ? listen : listen.drag || noop,
          dragended = listen.dragend || noop,
          noclick = false,
          view = select(event.view).on(name("dragstart selectstart"), nodefault, true),
          context = select(contextify.apply(that, args)).on(name(move), moved).on(name(end), ended);

      // I’d like to call preventDefault on mousedown to disable native dragging
      // of links or images and native text selection. However, in Chrome this
      // causes mousemove and mouseup events outside an iframe to be dropped:
      // https://bugs.chromium.org/p/chromium/issues/detail?id=269917
      // And if you preventDefault on touchstart on iOS, it prevents the click
      // event on touchend, even if there was no touchmove! So instead, we
      // cancel the specific undesirable behaviors.

      function name(types) {
        var name = id == null ? ".drag" : ".drag-" + id;
        return types == null ? name : types.trim()
            .split(/^|\s+/)
            .map(function(type) { return type + name; })
            .join(" ");
      }

      function moved() {
        var p = position(parent, id);
        if (p == null) return; // This touch didn’t change.
        nodefault(), noclick = true;
        dragged.call(that, p[0] + dx, p[1] + dy, id);
      }

      function ended() {
        var p = position(parent, id);
        if (p == null) return; // This touch didn’t end.
        view.on(name(), null);
        context.on(name(), null);
        if (noclick) view.on(name("click"), nodefault, true), setTimeout(afterended, 0);
        dragended.call(that, p[0] + dx, p[1] + dy, id);
      }

      function afterended() {
        view.on(name("click"), null);
      }
    };
  }

  drag.filter = function(_) {
    return arguments.length ? (filter = typeof _ === "function" ? _ : constant(!!_), drag) : filter;
  };

  drag.container = function(_) {
    return arguments.length ? (container = typeof _ === "function" ? _ : constant(_), drag) : container;
  };

  drag.x = function(_) {
    return arguments.length ? (x = typeof _ === "function" ? _ : constant(+_), drag) : x;
  };

  drag.y = function(_) {
    return arguments.length ? (y = typeof _ === "function" ? _ : constant(+_), drag) : y;
  };

  return drag;
}
<|endoftext|>


<commit_before>(function() {

    var regExpCache = {};

    function hasClass(element, className) {
        return (Object.prototype.hasOwnProperty.call(regExpCache, className) ?
                   regExpCache[className] :
                   (regExpCache[className] = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)'))).test(element.className);
    }

    function filterDOM(node, func) {
        var results = [];

        function walk(node) {
            if (func(node)) {
                results.push(node);
            }
            node = node.firstChild;
            while (node) {
                walk(node);
                node = node.nextSibling;
            }
        }

        walk(node);

        return results;
    }

/**

@property parjar.findAll

@parameter selector {string} The CSS selector for the search.

@parameter root {Document|Element} Optional element to use as the search start point.

@description

Search for all elements matching the CSS selector. Returns an array of the elements.

Acceptable simple selectors are of the following forms only.

    div
    #alpha
    .beta
    div.gamma

In the case of a #myId selector, the returned array will always have
zero or one elements. It is more likely that you want to call pajar.find when
using an id selector.

If the root element is supplied it is used as the starting point for the search.
The root element can be the result. If the root element is not supplied then
the current document is used as the search starting point.

pajar.findAll('#alpha');
pajar.findAll('div.gamma', document.body);

*/
    pajar.findAll = function(selector, root) {
        if ((arguments.length > 1) && !root) {
            throw new Error('pajar.findAll: the second argument can be omitted or an element but cannot be falsy.');
        }
        root = root || document;
        var matches;

        if (matches = selector.match(/^#(.*)$/)) {
            var id = matches[1];
            if (root.id === id) {
                return [root];
            }
            if ((typeof root.getElementById === 'function') ||
                ((typeof root.getElementById === 'object') &&
                 (root.getElementById !== null))) {
                var el = root.getElementById(id);
                return el ? [el] : [];
            }
            return filterDom(root, function(node) {
                return node.id === id;
            }).slice(0, 1);
        }

        matches = selector.match(/([^\.]*)\.*([^\.]*)/);
        var tagName = matches[1] || '*';
        var className = matches[2];

        var elements = root.getElementsByTagName(tagName);
        if ((!elements.length) && (tagName === '*') && root.all) {
            elements = root.all; // IE < 6
        }

        var results = [];

        if (((tagName === '*') ||
             (root.tagName && (root.tagName.toLowerCase() === tagName.toLowerCase()))) &&
            ((!className) ||
             hasClass(root, className))) {
            results.push(root);
        }

        if (className) {
            // filter for elements with correct className
            for (var i = 0, ilen = elements.length; i < ilen; ++i) {
                var element = elements[i];
                if (hasClass(element, className)) {
                    results.push(element);
                }
            }
        }
        else {
            for (var i = 0, ilen = elements.length; i < ilen; i++) {
                results.push(elements[i]);
            }
        }

        return results;
    };

/**

@property pajar.find

@parameter selector {string} The CSS selector for the search.

@parameter root {Document|Element} Optional element to use as the search start point.

@description

Search for the first element matching the CSS selector. A single element
or undefined is returned.

The rest of the details are the same as for pajar.findAll.

*/
    pajar.find = function(selector, root) {
        // use apply to preserve the number of arguments sent to findAll
        return pajar.findAll.apply(pajar, arguments)[0];
    };

}());
<commit_msg>Perhaps this check was too paranoid<commit_after>(function() {

    var regExpCache = {};

    function hasClass(element, className) {
        return (Object.prototype.hasOwnProperty.call(regExpCache, className) ?
                   regExpCache[className] :
                   (regExpCache[className] = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)'))).test(element.className);
    }

    function filterDOM(node, func) {
        var results = [];

        function walk(node) {
            if (func(node)) {
                results.push(node);
            }
            node = node.firstChild;
            while (node) {
                walk(node);
                node = node.nextSibling;
            }
        }

        walk(node);

        return results;
    }

/**

@property parjar.findAll

@parameter selector {string} The CSS selector for the search.

@parameter root {Document|Element} Optional element to use as the search start point.

@description

Search for all elements matching the CSS selector. Returns an array of the elements.

Acceptable simple selectors are of the following forms only.

    div
    #alpha
    .beta
    div.gamma

In the case of a #myId selector, the returned array will always have
zero or one elements. It is more likely that you want to call pajar.find when
using an id selector.

If the root element is supplied it is used as the starting point for the search.
The root element can be the result. If the root element is not supplied then
the current document is used as the search starting point.

pajar.findAll('#alpha');
pajar.findAll('div.gamma', document.body);

*/
    pajar.findAll = function(selector, root) {
        root = root || document;
        var matches;

        if (matches = selector.match(/^#(.*)$/)) {
            var id = matches[1];
            if (root.id === id) {
                return [root];
            }
            if ((typeof root.getElementById === 'function') ||
                ((typeof root.getElementById === 'object') &&
                 (root.getElementById !== null))) {
                var el = root.getElementById(id);
                return el ? [el] : [];
            }
            return filterDom(root, function(node) {
                return node.id === id;
            }).slice(0, 1);
        }

        matches = selector.match(/([^\.]*)\.*([^\.]*)/);
        var tagName = matches[1] || '*';
        var className = matches[2];

        var elements = root.getElementsByTagName(tagName);
        if ((!elements.length) && (tagName === '*') && root.all) {
            elements = root.all; // IE < 6
        }

        var results = [];

        if (((tagName === '*') ||
             (root.tagName && (root.tagName.toLowerCase() === tagName.toLowerCase()))) &&
            ((!className) ||
             hasClass(root, className))) {
            results.push(root);
        }

        if (className) {
            // filter for elements with correct className
            for (var i = 0, ilen = elements.length; i < ilen; ++i) {
                var element = elements[i];
                if (hasClass(element, className)) {
                    results.push(element);
                }
            }
        }
        else {
            for (var i = 0, ilen = elements.length; i < ilen; i++) {
                results.push(elements[i]);
            }
        }

        return results;
    };

/**

@property pajar.find

@parameter selector {string} The CSS selector for the search.

@parameter root {Document|Element} Optional element to use as the search start point.

@description

Search for the first element matching the CSS selector. A single element
or undefined is returned.

The rest of the details are the same as for pajar.findAll.

*/
    pajar.find = function(selector, root) {
        // use apply to preserve the number of arguments sent to findAll
        return pajar.findAll.apply(pajar, arguments)[0];
    };

}());
<|endoftext|>


<commit_before>/* Modal Implementation */
if (typeof define !== 'function') {
    var define = require('amdefine')(module);
}
define(["jquery", "./client", "./meta"], function($, $client, $meta) {
	"use strict";

   /**
    * A module implementing forms.
    * @module nor-ui.form
    */
	var exports = {
		'fields': {}
	};

	/** Default metadata for forms
	 */
	var _form_meta = {
		'_meta': {
			'types': {
				'year': {
					'type': 'multi',
					'options': {}
				}
			},
			'translations': {
				'fi': {
					'year': 'Vuosi',
					'submit': 'Lähetä'
				},
				'en': {
					'year': 'Year',
					'submit': 'Send'
				}
			}
		}
	};

	// Populate default year values
	var current_year = new Date().getFullYear();
	var i;
	for(i = current_year-20; i<=current_year; i+=1) {
		_form_meta._meta.types.year.options[i] = i;
	}

	/** Implementations of field types */
	exports.fields = {
		// Hidden field
		'hidden' : {
			'create': function(key, value, meta) {
				// FIXME: Maybe jquery could be avoided by using some other way
				var div = $('
');
				var input = $('<input type="hidden"/>').attr('value', value).attr('name', key);
				div.append(input);
				return div;
			}
		},
		// Location field
		// FIXME: Move Google Maps features to external module / implement modular way of extending features
		'location' : {
			'create': function(key, value, meta) {
				var div = $('
');
				var label = $('').text(meta.t(key));
				var input_lat = $('<input type="hidden"/>').attr('value', value.lat).attr('name', 'pos_lat');
				var input_long = $('<input type="hidden"/>').attr('value', value.long).attr('name', 'pos_long');
				var content_div = $('
');
				var map_div = $('
');
				content_div.append(input_lat);
				content_div.append(input_long);
				content_div.append(map_div);
				div.append(label);
				div.append(content_div);

				var lat, long;
				if(value && value.lat) {
					lat = parseFloat(value.lat);
				} else {
					lat = 65;
				}
				if( (lat === 0) || (lat === "0") ) { lat = 65; }

				if(value && value.long) {
					long = parseFloat(value.long);
				} else {
					long = 26;
				}
				if( (long === 0) || (long === "0") ) { long = 26; }

				function initialize() {

					//alert("lat=" + lat + ", long=" + long);

					var mapOptions = {
						zoom: 4,
						center: new google.maps.LatLng(lat, long),
						mapTypeId: google.maps.MapTypeId.ROADMAP
					};
					var map = new google.maps.Map(map_div.get(0), mapOptions);

					var store = {}, position;
					if(lat && long) {
						position = new google.maps.LatLng(lat, long);
						store.marker = new google.maps.Marker({
							position: position,
							map: map
						});
						map.panTo(position);
						$(input_lat).attr('value', lat);
						$(input_long).attr('value', long);
					}

					google.maps.event.addListener(map, 'click', function(e) {
						var position = e.latLng;
						var m = new google.maps.Marker({
							position: position,
							map: map
						});
						map.panTo(position);

						if(store.marker) {
							store.marker.setMap(null);
							delete store.marker;
						}
						store.marker = m;

						$(input_lat).attr('value', position.lat());
						$(input_long).attr('value', position.lng());
					});

				}

				//google.maps.event.addDomListener($(div).get(), 'load', initialize);

				function delayed_initialize_if_visible(div) {
					if( $(div).is(':visible') ) {
						//alert("map div visible");
						setTimeout(function() {
							initialize();
						}, 100);
						return;
					}
					setTimeout(function() {
						delayed_initialize_if_visible(div);
					}, 500);
				}

				$(div).ready(function() {
					//alert("map div ready");
					delayed_initialize_if_visible(div);
				});

				return div;
			}
		},
		// File field
		'file' : {
			'create': function(key, value, meta, parent_div) {
				var type = meta.getType(key);
				var div = $('
');
				var label = $('').text(meta.t(key));
				var form_div = $('
');
				var input = $('<input type="file" />').attr('name', key);
				var form = $('<form enctype="multipart/form-data" />');
				form.append( $('<input type="hidden" name="MAX_FILE_SIZE" value="10485760" />') );
				var progress = $('<progress/>');
				var status = $('
');
				var form_action = $(parent_div).attr('data-action');

				status.hide();
				progress.hide();

				form.append( $('<input type="hidden" name="_action" value="put" />') );
				form.append(input);
				form_div.append(form);
				form_div.append(progress);
				form_div.append(status);

				div.append(label);
				div.append(form_div);

				// Parse action
				var url_parts = form_action.split('?');
				var url_base = url_parts.shift();
				var url_params = url_parts.join('?');

				function progressHandlingFunction(e){
					if(e.lengthComputable){
						progress.attr({value:e.loaded,max:e.total});
					}
				}

				input.change(function(){
					var file = this.files[0];
					var ext = file.name.split('.').reverse()[0];
					var formData = new FormData(form[0]);

					var url = url_base+'/'+encodeURIComponent(key)+'.'+encodeURIComponent(ext);
					if(url_params) {
						url += '?' + url_params;
					}

					$.ajax({
						url: url,
						type: 'POST',
						xhr: function() {  // custom xhr
							var myXhr = $.ajaxSettings.xhr();
							if(myXhr.upload){ // check if upload property exists
								myXhr.upload.addEventListener('progress',progressHandlingFunction, false); // for handling the progress of the upload
							}
							return myXhr;
						},
						beforeSend: function() {
							progress.show();
						},
						success: function() {
							progress.hide();
							// FIXME: Implement some kind of notice when ready
							status.attr('class', 'success');
							status.text('OK');
							status.show();
						},
						error: function() {
							// FIXME: Implement better error messages
							progress.hide();
							status.text("ERROR");
							status.attr('class', 'fail');
							status.show();
						},
						data: formData,
						cache: false,
						contentType: false,
						processData: false
					});
				});

				return div;
			}
		},
		// Text field
		'multi' : {
			'create': function(key, value, meta) {
				var type = meta.getType(key);
				var div = $('
');
				var label = $('').text(meta.t(key));
				var select = $('<select/>').attr('selected', value).attr('name', key);
				$(select).append( $('<option/>').attr('value', '').text('Valitse') );
				$.each(type.options, function(k, v) {
					var option = $('<option/>').attr('value', k).text(v);
					if(k === value) {
						option.attr('selected', 'selected');
					}
					$(select).append( option );
				});
				div.append(label);
				div.append(select);
				return div;
			}
		},
		// Year field
		'year' : {
			'create': function(key, value, meta) {
				return exports.fields.multi.create(key, value, $meta.parse(_form_meta) );
			}
		},
		// Text field
		'text' : {
			'create': function(key, value, meta) {
				var div = $('
');
				var label = $('').text(meta.t(key));
				var input = $('<input type="text"/>').attr('value', value).attr('name', key);
				div.append(label);
				div.append(input);
				return div;
			}
		},
		// Textarea field
		'textarea' : {
			'create': function(key, value, meta) {
				var div = $('
');
				var label = $('').text(meta.t(key));
				var input = $('<textarea>').attr('name', key).text(value);
				div.append(label);
				div.append(input);
				return div;
			}
		},
		// Submit button
		'submit' : {
			'create': function(key, value, meta) {
				return $('
').append( $('<input class="btn" type="submit">').attr('value', meta.t('submit')) );
			}
		}
	};

	/**
	 * @callback initForm~options~successCallback
	 * @param {object} form - HTML element
	 */

	/**
	 * @typedef initForm~options
	 * @type {object}
	 * @property {initForm~options~successCallback} success - Callback which will be called after the form has been built.
	 */

	/** Initialize forms
	 * @param {object|string} obj - Element where the form will be created. It can also be JQuery selector string.
	 * @param {initForm~options} opts - Options for initialization
	 */
	exports.initForm = function(obj, opts) {
			opts = opts || {};
			var form_div = $(obj);
			var action = $(form_div).attr('data-action');
			var method = (''+($(form_div).attr('data-method') || 'post')).toLowerCase();
			var fields_from = $(form_div).attr('data-fields-from') || action;

			var data_fields_ignore = $(form_div).attr('data-fields-ignore');
			var fields_ignore = [];
			if(data_fields_ignore) {
				fields_ignore = (''+data_fields_ignore).split(/ +/);
			}

			var form = $('<form/>');

			if(method !== "post") {
				form.append( $('<input type="hidden" name="_action"/>').attr('value', method) );
			}

			$(form).submit(function() {
				if( (method === "post") || (method === "delete") ) {
					//alert("Posting to " + action + "...");
					$.post(action, $(form).serialize(), function() {
						$(form).trigger('reset');
						if(opts.success) {
							opts.success(form_div);
						} else {
							// FIXME: There should be better way than alert()!
							alert("OK");
						}
					}).fail(function() {
						alert("Operation failed!");
					});
				} else {
					// FIXME: Add an error message -- unknown method!
					alert("Unknown form method");
				}
				return false;
			});

			if(fields_from) {
				$client.get(fields_from, function(data) {
					var meta = $meta.parse(data);
					$.each(data, function(key, val) {

						// Ignore internal fields
						if(key[0] === '_') { return; }

						// Ignore user defined fields
						if($.inArray('*', fields_ignore) >= 0) { return; }
						if($.inArray(key, fields_ignore) >= 0) { return; }

						// Append div based on type
						var type = meta.getType(key);
						if( type && (typeof type === 'object') && type.type) {
							type = type.type;
						}
						if(exports.fields[type] && exports.fields[type].create) {
							$(form).append(exports.fields[type].create(key, val, meta, form_div));
						} else {
							$(form).append( $('
').append( $('
').text('Undefined #' + key + ' of type ' + JSON.stringify(type) ) ) );
						}
					});
					$(form).append( exports.fields.submit.create(undefined, undefined, $meta.parse(_form_meta), form_div) );
				});
			}

			$(form_div).append(form);
	};

	/** Initialize forms
	 */
	exports.init = function(obj) {

		/* Setup forms with data */
		$(obj).find(".form").each(function() {
			var form_div = this;
			exports.initForm(form_div);
		});

	};

	/** Create form
	 */
	exports.create = function(opts) {
		opts = opts || {};

		var success_fn;
		if(opts.success) {
			success_fn = opts.success;
			delete opts.success;
		}

		var data = {
			"action": opts.action,
			"method": opts.method || 'post',
			"fields-from": opts.fields_from,
			"fields-ignore": opts.fields_ignore
		};

		var div = $('
');
		$.each(data, function(key, value) {
			if(data[key]) {
				div.attr('data-'+key, value);
			}
		});
		exports.initForm(div, {'success':success_fn} );
		return div;
	};

	/* Initialize stuff after page is loaded */
	$(function () {
		exports.init(this);
	});

	// End of library code
	return exports;
});
/* EOF */
<commit_msg>Testing jsdoc<commit_after>/* Modal Implementation */
if (typeof define !== 'function') {
    var define = require('amdefine')(module);
}
define(["jquery", "./client", "./meta"], function($, $client, $meta) {
	"use strict";

   /**
    * A module implementing forms.
    * @module nor-ui/form
    */
	var exports = {
		'fields': {}
	};

	/** Default metadata for forms
	 */
	var _form_meta = {
		'_meta': {
			'types': {
				'year': {
					'type': 'multi',
					'options': {}
				}
			},
			'translations': {
				'fi': {
					'year': 'Vuosi',
					'submit': 'Lähetä'
				},
				'en': {
					'year': 'Year',
					'submit': 'Send'
				}
			}
		}
	};

	// Populate default year values
	var current_year = new Date().getFullYear();
	var i;
	for(i = current_year-20; i<=current_year; i+=1) {
		_form_meta._meta.types.year.options[i] = i;
	}

	/** Implementations of field types */
	exports.fields = {
		// Hidden field
		'hidden' : {
			'create': function(key, value, meta) {
				// FIXME: Maybe jquery could be avoided by using some other way
				var div = $('
');
				var input = $('<input type="hidden"/>').attr('value', value).attr('name', key);
				div.append(input);
				return div;
			}
		},
		// Location field
		// FIXME: Move Google Maps features to external module / implement modular way of extending features
		'location' : {
			'create': function(key, value, meta) {
				var div = $('
');
				var label = $('').text(meta.t(key));
				var input_lat = $('<input type="hidden"/>').attr('value', value.lat).attr('name', 'pos_lat');
				var input_long = $('<input type="hidden"/>').attr('value', value.long).attr('name', 'pos_long');
				var content_div = $('
');
				var map_div = $('
');
				content_div.append(input_lat);
				content_div.append(input_long);
				content_div.append(map_div);
				div.append(label);
				div.append(content_div);

				var lat, long;
				if(value && value.lat) {
					lat = parseFloat(value.lat);
				} else {
					lat = 65;
				}
				if( (lat === 0) || (lat === "0") ) { lat = 65; }

				if(value && value.long) {
					long = parseFloat(value.long);
				} else {
					long = 26;
				}
				if( (long === 0) || (long === "0") ) { long = 26; }

				function initialize() {

					//alert("lat=" + lat + ", long=" + long);

					var mapOptions = {
						zoom: 4,
						center: new google.maps.LatLng(lat, long),
						mapTypeId: google.maps.MapTypeId.ROADMAP
					};
					var map = new google.maps.Map(map_div.get(0), mapOptions);

					var store = {}, position;
					if(lat && long) {
						position = new google.maps.LatLng(lat, long);
						store.marker = new google.maps.Marker({
							position: position,
							map: map
						});
						map.panTo(position);
						$(input_lat).attr('value', lat);
						$(input_long).attr('value', long);
					}

					google.maps.event.addListener(map, 'click', function(e) {
						var position = e.latLng;
						var m = new google.maps.Marker({
							position: position,
							map: map
						});
						map.panTo(position);

						if(store.marker) {
							store.marker.setMap(null);
							delete store.marker;
						}
						store.marker = m;

						$(input_lat).attr('value', position.lat());
						$(input_long).attr('value', position.lng());
					});

				}

				//google.maps.event.addDomListener($(div).get(), 'load', initialize);

				function delayed_initialize_if_visible(div) {
					if( $(div).is(':visible') ) {
						//alert("map div visible");
						setTimeout(function() {
							initialize();
						}, 100);
						return;
					}
					setTimeout(function() {
						delayed_initialize_if_visible(div);
					}, 500);
				}

				$(div).ready(function() {
					//alert("map div ready");
					delayed_initialize_if_visible(div);
				});

				return div;
			}
		},
		// File field
		'file' : {
			'create': function(key, value, meta, parent_div) {
				var type = meta.getType(key);
				var div = $('
');
				var label = $('').text(meta.t(key));
				var form_div = $('
');
				var input = $('<input type="file" />').attr('name', key);
				var form = $('<form enctype="multipart/form-data" />');
				form.append( $('<input type="hidden" name="MAX_FILE_SIZE" value="10485760" />') );
				var progress = $('<progress/>');
				var status = $('
');
				var form_action = $(parent_div).attr('data-action');

				status.hide();
				progress.hide();

				form.append( $('<input type="hidden" name="_action" value="put" />') );
				form.append(input);
				form_div.append(form);
				form_div.append(progress);
				form_div.append(status);

				div.append(label);
				div.append(form_div);

				// Parse action
				var url_parts = form_action.split('?');
				var url_base = url_parts.shift();
				var url_params = url_parts.join('?');

				function progressHandlingFunction(e){
					if(e.lengthComputable){
						progress.attr({value:e.loaded,max:e.total});
					}
				}

				input.change(function(){
					var file = this.files[0];
					var ext = file.name.split('.').reverse()[0];
					var formData = new FormData(form[0]);

					var url = url_base+'/'+encodeURIComponent(key)+'.'+encodeURIComponent(ext);
					if(url_params) {
						url += '?' + url_params;
					}

					$.ajax({
						url: url,
						type: 'POST',
						xhr: function() {  // custom xhr
							var myXhr = $.ajaxSettings.xhr();
							if(myXhr.upload){ // check if upload property exists
								myXhr.upload.addEventListener('progress',progressHandlingFunction, false); // for handling the progress of the upload
							}
							return myXhr;
						},
						beforeSend: function() {
							progress.show();
						},
						success: function() {
							progress.hide();
							// FIXME: Implement some kind of notice when ready
							status.attr('class', 'success');
							status.text('OK');
							status.show();
						},
						error: function() {
							// FIXME: Implement better error messages
							progress.hide();
							status.text("ERROR");
							status.attr('class', 'fail');
							status.show();
						},
						data: formData,
						cache: false,
						contentType: false,
						processData: false
					});
				});

				return div;
			}
		},
		// Text field
		'multi' : {
			'create': function(key, value, meta) {
				var type = meta.getType(key);
				var div = $('
');
				var label = $('').text(meta.t(key));
				var select = $('<select/>').attr('selected', value).attr('name', key);
				$(select).append( $('<option/>').attr('value', '').text('Valitse') );
				$.each(type.options, function(k, v) {
					var option = $('<option/>').attr('value', k).text(v);
					if(k === value) {
						option.attr('selected', 'selected');
					}
					$(select).append( option );
				});
				div.append(label);
				div.append(select);
				return div;
			}
		},
		// Year field
		'year' : {
			'create': function(key, value, meta) {
				return exports.fields.multi.create(key, value, $meta.parse(_form_meta) );
			}
		},
		// Text field
		'text' : {
			'create': function(key, value, meta) {
				var div = $('
');
				var label = $('').text(meta.t(key));
				var input = $('<input type="text"/>').attr('value', value).attr('name', key);
				div.append(label);
				div.append(input);
				return div;
			}
		},
		// Textarea field
		'textarea' : {
			'create': function(key, value, meta) {
				var div = $('
');
				var label = $('').text(meta.t(key));
				var input = $('<textarea>').attr('name', key).text(value);
				div.append(label);
				div.append(input);
				return div;
			}
		},
		// Submit button
		'submit' : {
			'create': function(key, value, meta) {
				return $('
').append( $('<input class="btn" type="submit">').attr('value', meta.t('submit')) );
			}
		}
	};

	/**
	 * @callback initForm~options~successCallback
	 * @param {object} form - HTML element
	 */

	/**
	 * @typedef initForm~options
	 * @type {object}
	 * @property {initForm~options~successCallback} success - Callback which will be called after the form has been built.
	 */

	/** Initialize forms
	 * @param {object|string} obj - Element where the form will be created. It can also be JQuery selector string.
	 * @param {initForm~options} opts - Options for initialization
	 */
	exports.initForm = function(obj, opts) {
			opts = opts || {};
			var form_div = $(obj);
			var action = $(form_div).attr('data-action');
			var method = (''+($(form_div).attr('data-method') || 'post')).toLowerCase();
			var fields_from = $(form_div).attr('data-fields-from') || action;

			var data_fields_ignore = $(form_div).attr('data-fields-ignore');
			var fields_ignore = [];
			if(data_fields_ignore) {
				fields_ignore = (''+data_fields_ignore).split(/ +/);
			}

			var form = $('<form/>');

			if(method !== "post") {
				form.append( $('<input type="hidden" name="_action"/>').attr('value', method) );
			}

			$(form).submit(function() {
				if( (method === "post") || (method === "delete") ) {
					//alert("Posting to " + action + "...");
					$.post(action, $(form).serialize(), function() {
						$(form).trigger('reset');
						if(opts.success) {
							opts.success(form_div);
						} else {
							// FIXME: There should be better way than alert()!
							alert("OK");
						}
					}).fail(function() {
						alert("Operation failed!");
					});
				} else {
					// FIXME: Add an error message -- unknown method!
					alert("Unknown form method");
				}
				return false;
			});

			if(fields_from) {
				$client.get(fields_from, function(data) {
					var meta = $meta.parse(data);
					$.each(data, function(key, val) {

						// Ignore internal fields
						if(key[0] === '_') { return; }

						// Ignore user defined fields
						if($.inArray('*', fields_ignore) >= 0) { return; }
						if($.inArray(key, fields_ignore) >= 0) { return; }

						// Append div based on type
						var type = meta.getType(key);
						if( type && (typeof type === 'object') && type.type) {
							type = type.type;
						}
						if(exports.fields[type] && exports.fields[type].create) {
							$(form).append(exports.fields[type].create(key, val, meta, form_div));
						} else {
							$(form).append( $('
').append( $('
').text('Undefined #' + key + ' of type ' + JSON.stringify(type) ) ) );
						}
					});
					$(form).append( exports.fields.submit.create(undefined, undefined, $meta.parse(_form_meta), form_div) );
				});
			}

			$(form_div).append(form);
	};

	/** Initialize forms
	 */
	exports.init = function(obj) {

		/* Setup forms with data */
		$(obj).find(".form").each(function() {
			var form_div = this;
			exports.initForm(form_div);
		});

	};

	/** Create form
	 */
	exports.create = function(opts) {
		opts = opts || {};

		var success_fn;
		if(opts.success) {
			success_fn = opts.success;
			delete opts.success;
		}

		var data = {
			"action": opts.action,
			"method": opts.method || 'post',
			"fields-from": opts.fields_from,
			"fields-ignore": opts.fields_ignore
		};

		var div = $('
');
		$.each(data, function(key, value) {
			if(data[key]) {
				div.attr('data-'+key, value);
			}
		});
		exports.initForm(div, {'success':success_fn} );
		return div;
	};

	/* Initialize stuff after page is loaded */
	$(function () {
		exports.init(this);
	});

	// End of library code
	return exports;
});
/* EOF */
<|endoftext|>


<commit_before>var MineField = require('./minefield');
var FieldLocationArtist = require('./artists/fieldlocationartist');
var CursorArtist = require('./artists/cursorartist');
var CanvasMetrics = require('./artists/canvasmetrics');
var Cursor = require('./cursor');
var EventDispatcher = require('./eventdispatcher');
var MinePlacer = require('./mineplacer');

var Game = function(options) {
  if (typeof options === 'undefined') {
    options = {};
  }

  var canvasId = options.canvas || "landmine";
  var canvas = document.getElementById(canvasId);
  this.context = canvas.getContext('2d');
  this.canvas = canvas;

  this.canvasSize = {
    width: canvas.width,
    height: canvas.height
  };

  this.field = new MineField({
    width: 15,
    height: 12
  });

  this.metrics = new CanvasMetrics({
    canvasSize: this.canvasSize,
    fieldSize: this.field
  });

  this.locationArtist = new FieldLocationArtist({
    metrics: this.metrics,
    context: this.context,
    field:   this.field
  });

  this.cursorArtist = new CursorArtist({
    context: this.context,
    metrics: this.metrics
  });

  this.cursor = new Cursor(0, 0, this.field);

  var miner = new MinePlacer();
  miner.placeMines(this.field, 20);

  this.bindEvents();
};

Game.prototype.draw = function() {
  var self = this;

  this.clear();

  this.field.forEach(function(location, x, y) {
    self.locationArtist.draw(location, x, y);
  });

  this.cursorArtist.draw(this.cursor.x, this.cursor.y);
};

Game.prototype.start = function() {
  this.draw();
};

Game.prototype.clear = function() {
  this.context.clearRect(0, 0, this.canvasSize.width, this.canvasSize.height);
};

Game.prototype.bindEvents = function() {
  var self = this;
  var dispatcher = new EventDispatcher(this.canvas);
  dispatcher.on('move:left', function() {
    self.cursor.moveLeft();
    self.draw();
  });

  dispatcher.on('move:right', function() {
    self.cursor.moveRight();
    self.draw();
  });

  dispatcher.on('move:up', function() {
    self.cursor.moveUp();
    self.draw();
  });

  dispatcher.on('move:down', function() {
    self.cursor.moveDown();
    self.draw();
  });

  dispatcher.on('dig', function() {
    var spot = self.field.get(self.cursor.x, self.cursor.y);

    if (spot.hasMine) {
      self.field.detonateMines();
    } else {
      spot.dig();
    }

    self.draw();
  });

  dispatcher.on('flag', function() {
    self.field.get(self.cursor.x, self.cursor.y).flag();
    self.draw();
  });

};

module.exports = Game;
<commit_msg>make game official size of 14x10<commit_after>var MineField = require('./minefield');
var FieldLocationArtist = require('./artists/fieldlocationartist');
var CursorArtist = require('./artists/cursorartist');
var CanvasMetrics = require('./artists/canvasmetrics');
var Cursor = require('./cursor');
var EventDispatcher = require('./eventdispatcher');
var MinePlacer = require('./mineplacer');

var Game = function(options) {
  if (typeof options === 'undefined') {
    options = {};
  }

  var canvasId = options.canvas || "landmine";
  var canvas = document.getElementById(canvasId);
  this.context = canvas.getContext('2d');
  this.canvas = canvas;

  this.canvasSize = {
    width: canvas.width,
    height: canvas.height
  };

  this.field = new MineField({
    width: 14,
    height: 10
  });

  this.metrics = new CanvasMetrics({
    canvasSize: this.canvasSize,
    fieldSize: this.field
  });

  this.locationArtist = new FieldLocationArtist({
    metrics: this.metrics,
    context: this.context,
    field:   this.field
  });

  this.cursorArtist = new CursorArtist({
    context: this.context,
    metrics: this.metrics
  });

  this.cursor = new Cursor(0, 0, this.field);

  var miner = new MinePlacer();
  miner.placeMines(this.field, 20);

  this.bindEvents();
};

Game.prototype.draw = function() {
  var self = this;

  this.clear();

  this.field.forEach(function(location, x, y) {
    self.locationArtist.draw(location, x, y);
  });

  this.cursorArtist.draw(this.cursor.x, this.cursor.y);
};

Game.prototype.start = function() {
  this.draw();
};

Game.prototype.clear = function() {
  this.context.clearRect(0, 0, this.canvasSize.width, this.canvasSize.height);
};

Game.prototype.bindEvents = function() {
  var self = this;
  var dispatcher = new EventDispatcher(this.canvas);
  dispatcher.on('move:left', function() {
    self.cursor.moveLeft();
    self.draw();
  });

  dispatcher.on('move:right', function() {
    self.cursor.moveRight();
    self.draw();
  });

  dispatcher.on('move:up', function() {
    self.cursor.moveUp();
    self.draw();
  });

  dispatcher.on('move:down', function() {
    self.cursor.moveDown();
    self.draw();
  });

  dispatcher.on('dig', function() {
    var spot = self.field.get(self.cursor.x, self.cursor.y);

    if (spot.hasMine) {
      self.field.detonateMines();
    } else {
      spot.dig();
    }

    self.draw();
  });

  dispatcher.on('flag', function() {
    self.field.get(self.cursor.x, self.cursor.y).flag();
    self.draw();
  });

};

module.exports = Game;
<|endoftext|>