<commit_before>/**
 * Copyright (c) 2009
 * Jan-Felix Schwarz
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 **/

MOVI.namespace("model");

(function() {

	var _CLASS_NAME = "movi-canvas";

	/**
     * Canvas provides a wrapper object for the model's root shape.
     * @namespace MOVI.model
     * @class MOVI.model.Canvas
     * @extends MOVI.model.Shape
     * @constructor
	 * @param {Modelviewer} modelviewer The Modelviewer object that owns
	 * the canvas
     * @param {Object} jsonObj The JSON object from which the new canvas
     * is created.
	 * @param {String} prefix The element's ID prefix (unique per modelviewer)
     */
    MOVI.model.Canvas = function(modelviewer, jsonObj, prefix) {

		this._modelviewer = modelviewer;

		// element's attributes
		var attr = {};

		MOVI.model.Canvas.superclass.constructor.call(this, jsonObj, jsonObj.stencilset, null, prefix, attr);

		this.set("className", _CLASS_NAME);

		this._indexShapes();

		this._update();

	}

	MOVI.extend(MOVI.model.Canvas, MOVI.model.Shape, {

		/**
		 * The owning modelviewer
		 * @property modelviewer
		 * @type Modelviewer
		 * @private
		 */
		_modelviewer: null,

		/**
		 * A key map containing all shapes of the model with their
		 * resource ids as keys.
		 * @property shapes
		 * @type Object
		 */
		shapes: {},

		/**
	     * Index all shapes owned by the model. Deep traverse canvas'
	     * child shapes and add all objects to the 'shapes' property.
	     * @method _indexShapes
		 * @param {Shape} recShape (optional) Temporarily considered shape
		 * for recursion
	     * @private
	     */
		_indexShapes: function(recShape) {
			recShape = recShape || this;
			for(key in recShape.childShapes) {
				var child = recShape.childShapes[key];
				this.shapes[child.resourceId] = child;
				this._indexShapes(child);
			}
		},

		/**
	     * Update style properties of the element
	     * @method _update
	     * @private
	     */
		_update: function() {
			var minX, minY;
			for(i in this.childShapes) {
				if(minX==undefined) minX = this.childShapes[i].getAbsBounds().upperLeft.x;
				else minX = Math.min(minX, this.childShapes[i].getAbsBounds().upperLeft.x);
				if(minY==undefined) minY = this.childShapes[i].getAbsBounds().upperLeft.y;
				else minY = Math.min(minY, this.childShapes[i].getAbsBounds().upperLeft.y);
			}
			for(i in this.childShapes) {
				this.childShapes[i].bounds.upperLeft.x -= minX;
				this.childShapes[i].bounds.upperLeft.y -= minY;
				this.childShapes[i].bounds.lowerRight.x -= minX;
				this.childShapes[i].bounds.lowerRight.y -= minY;
				this.childShapes[i].update();
			}
			var left = (MOVI.config.MODEL_MARGIN / 2) + "px";
			var top = (MOVI.config.MODEL_MARGIN / 2) + "px";
			var width = (this._modelviewer.getImgWidth() - MOVI.config.MODEL_MARGIN) + "px";
			var height = (this._modelviewer.getImgHeight() - MOVI.config.MODEL_MARGIN) + "px";
			this.setStyle("left", left);
			this.setStyle("top", top);
			this.setStyle("width", width);
			this.setStyle("height", height);
		},

		/**
	     * Returns the shape with the specified resource id.
		 * If no matching stencil is found null is returned.
	     * @method getShape
	     * @param resourceId The shape's resource id
	     */
		getShape: function(resourceId) {
			return this.shapes[resourceId] || null;
		},

		/**
		 * Returns the owning modelviewer
		 * @method getModelViewer
		 * @return {ModelViewer} The owning model viewer
		 */
		getModelViewer: function() {
			return this._modelviewer;
		},

		getNodes: function() {
			var nodes = {};
			for(key in this.shapes) {
				if(this.shapes[key].stencil.type=="node")
					nodes[key] = this.shapes[key];
			}
			return nodes;
		},

		getEdges: function() {
			var edges = {};
			for(key in this.shapes) {
				if(this.shapes[key].stencil.type=="edge")
					edges[key] = this.shapes[key];
			}
			return edges;
		}

	});

})();<commit_msg>Fixed a bug in the canvas class<commit_after>/**
 * Copyright (c) 2009
 * Jan-Felix Schwarz
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 **/

MOVI.namespace("model");

(function() {

	var _CLASS_NAME = "movi-canvas";

	/**
     * Canvas provides a wrapper object for the model's root shape.
     * @namespace MOVI.model
     * @class MOVI.model.Canvas
     * @extends MOVI.model.Shape
     * @constructor
	 * @param {Modelviewer} modelviewer The Modelviewer object that owns
	 * the canvas
     * @param {Object} jsonObj The JSON object from which the new canvas
     * is created.
	 * @param {String} prefix The element's ID prefix (unique per modelviewer)
     */
    MOVI.model.Canvas = function(modelviewer, jsonObj, prefix) {

		this._modelviewer = modelviewer;

		// element's attributes
		var attr = {};

		MOVI.model.Canvas.superclass.constructor.call(this, jsonObj, jsonObj.stencilset, null, prefix, attr);

		this.set("className", _CLASS_NAME);

		this.shapes = {};
		this._indexShapes();

		this._update();

	}

	MOVI.extend(MOVI.model.Canvas, MOVI.model.Shape, {

		/**
		 * The owning modelviewer
		 * @property modelviewer
		 * @type Modelviewer
		 * @private
		 */
		_modelviewer: null,

		/**
		 * A key map containing all shapes of the model with their
		 * resource ids as keys.
		 * @property shapes
		 * @type Object
		 */
		shapes: null,

		/**
	     * Index all shapes owned by the model. Deep traverse canvas'
	     * child shapes and add all objects to the 'shapes' property.
	     * @method _indexShapes
		 * @param {Shape} recShape (optional) Temporarily considered shape
		 * for recursion
	     * @private
	     */
		_indexShapes: function(recShape) {
			recShape = recShape || this;
			for(key in recShape.childShapes) {
				var child = recShape.childShapes[key];
				this.shapes[child.resourceId] = child;
				this._indexShapes(child);
			}
		},

		/**
	     * Update style properties of the element
	     * @method _update
	     * @private
	     */
		_update: function() {
			var minX, minY;
			for(i in this.childShapes) {
				if(minX==undefined) minX = this.childShapes[i].getAbsBounds().upperLeft.x;
				else minX = Math.min(minX, this.childShapes[i].getAbsBounds().upperLeft.x);
				if(minY==undefined) minY = this.childShapes[i].getAbsBounds().upperLeft.y;
				else minY = Math.min(minY, this.childShapes[i].getAbsBounds().upperLeft.y);
			}
			for(i in this.childShapes) {
				this.childShapes[i].bounds.upperLeft.x -= minX;
				this.childShapes[i].bounds.upperLeft.y -= minY;
				this.childShapes[i].bounds.lowerRight.x -= minX;
				this.childShapes[i].bounds.lowerRight.y -= minY;
				this.childShapes[i].update();
			}
			var left = (MOVI.config.MODEL_MARGIN / 2) + "px";
			var top = (MOVI.config.MODEL_MARGIN / 2) + "px";
			var width = (this._modelviewer.getImgWidth() - MOVI.config.MODEL_MARGIN) + "px";
			var height = (this._modelviewer.getImgHeight() - MOVI.config.MODEL_MARGIN) + "px";
			this.setStyle("left", left);
			this.setStyle("top", top);
			this.setStyle("width", width);
			this.setStyle("height", height);
		},

		/**
	     * Returns the shape with the specified resource id.
		 * If no matching stencil is found null is returned.
	     * @method getShape
	     * @param resourceId The shape's resource id
	     */
		getShape: function(resourceId) {
			return this.shapes[resourceId] || null;
		},

		/**
		 * Returns the owning modelviewer
		 * @method getModelViewer
		 * @return {ModelViewer} The owning model viewer
		 */
		getModelViewer: function() {
			return this._modelviewer;
		},

		/**
		 *
		 *
		 */
		getNodes: function() {
			var nodes = {};
			for(key in this.shapes) {
				if(this.shapes[key].stencil.type=="node")
					nodes[key] = this.shapes[key];
			}
			return nodes;
		},

		getEdges: function() {
			var edges = {};
			for(key in this.shapes) {
				if(this.shapes[key].stencil.type=="edge")
					edges[key] = this.shapes[key];
			}
			return edges;
		}

	});

})();<|endoftext|>


<commit_before>
//This method is used to force the month and year to be two digits
function pad(num, length) {
    var s = "00" + num;
    return s.substr(s.length - length);
}

// Action for button "Pay with Ajax or Redirect"
function payAjaxOrRedirect(ajaxUrl,
                           redirectUrl,
                           cardRegistrationURL,
                           preregistrationData,
                           accessKey,
                           successRedirect,
                           failureRedirect)
{

    $('#submit-button').attr('disabled', true);

    mangoPay.cardRegistration.init({
        cardRegistrationURL : cardRegistrationURL,
        preregistrationData : preregistrationData,
        accessKey : accessKey
    });

    // Collect sensitive card data from the form
    var month = $("[data-id='troopers_mangopay_card_expiry_month']").val();
    var year = $("[data-id='troopers_mangopay_card_expiry_year']").val();

    var cardData = {
        cardNumber : $("[data-id='troopers_mangopay_card_number']").val(),
        cardExpirationDate : pad(month, 2) + "" + pad(year, 2),
        cardCvx : pad($("[data-id='troopers_mangopay_ccv']").val(), 3)
    };

    // Process data
    mangoPay.cardRegistration.sendDataWithAjaxOrRedirect(
        // URL to capture response when CORS is available
        ajaxUrl,
        // URL to capture response when CORS is not available
        redirectUrl,
        // Card data
        cardData,
        // Result Ajax callback
        function(data) {
            var json = $.parseJSON(data);
            if (json.success) {
                if (json.hasOwnProperty("redirect")) {
                    window.location = json.redirect;
                } else {
                    window.location = successRedirect;
                }
            } else {
                $('#alert-container').empty();
                if (json.message) {
                    var message = json.message;
                } else {
                    var message = 'Une erreur s\'est produite lors de votre réservation, veuillez vérifier vos informations et réessayer. Si l\'erreur persiste, n\'hésitez pas à contacter le support.';
                }
                var alert = '
\
                    <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>\
                    \
                    ' + message + '\

';
                $('#alert-container').append(alert);
                window.scrollTo(0, 0);
                $('#submit-button').attr('disabled', false);
            }

        },
        // Error ajax callback
        function(xhr, status, error){
            $('#alert-container').empty();
            var alert = '
\
                <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>\
                \
                Une erreur s\'est produite lors de votre achat, veuillez vérifier vos informations et réessayer. Si l\'erreur persiste, n\'hésitez pas à contacter le support.\

';
            window.scrollTo(0, 0);
            $('#alert-container').append(alert);
            $('#submit-button').attr('disabled', false);
        }
    );
}

var mangoPay = {

  cardRegistration : {
      _cardRegisterData: null,

    /**
     * Initialize card registration object
     *
     * @param {object} cardRegisterData Card pre-registration data {cardRegistrationURL, preregistrationData, accessKey}
     */
    init : function(cardRegisterData) {

        mangoPay._cardRegisterData = cardRegisterData;

    },

    /**
     * Processes card registration and sends the result to given URL asynchronously
     * Requires a browser that supports cross-origin Ajax calls
     *
     * @param {string} ajaxUrl Your page to load asynchronously to process the payment
     * @param {object} data Sensitive card details {cardNumber, cardExpirationDate, cardCvx}
     * @param {function} resultCallback A function to invoke when the call to given ajaxUrl succeeds
     * @param {function} errorCallback A function to invoke when the call to given ajaxUrl fails
     */
    sendDataWithAjax : function(ajaxUrl, data, resultCallback, errorCallback) {

        // Get Payline token
        mangoPay._ajax({

            // Payline expects POST
            type: "post",

            // Payline service URL
            url: mangoPay._cardRegisterData.cardRegistrationURL,

            // Force CORS
            crossDomain: true,

            // Sensitive card data plus pre-registration data and access key
            data: {
                data: mangoPay._cardRegisterData.preregistrationData,
                accessKeyRef: mangoPay._cardRegisterData.accessKey,
                cardNumber: data.cardNumber,
                cardExpirationDate: data.cardExpirationDate,
                cardCvx: data.cardCvx
            },

            // Forward response to the return URL
            success: function(data) {

                var dataToSend = "";

                // Prepare data
                if (data === null ) {
                    dataToSend = { errorCode: '' };
                } else if (data.indexOf("data=") === 0) {
                    dataToSend = { data: data.replace("data=", "") };
                } else {
                    dataToSend = { errorCode: data.replace("errorCode=", "") };
                }

                // Send data to the return page
                mangoPay._ajax({
                    type: "get",
                    url: ajaxUrl,
                    data: dataToSend,
                    success: resultCallback,
                    error: errorCallback
                });

            },

            error: errorCallback

        });
    },

    /**
     * Processes card registration and sends the result to given URL asynchronously or redirects browser to the given URL to capture result
     * Automatically detects if browser is capable of making cross-origin Ajax calls
     *
     * @param {string} ajaxUrl Your page to call asynchronously to process the payment
     * @param {string} redirectUrl Your page browser will be redirected to process the payment
     * @param {object} data Sensitive card details {cardNumber, cardExpirationDate, cardCvx}
     * @param {function} resultCallback A function to invoke when the call to given ajaxUrl succeeds
     * @param {function} errorCallback A function to invoke when the call to given ajaxUrl fails
     */
    sendDataWithAjaxOrRedirect: function(ajaxUrl, redirectUrl, data, resultCallback, errorCallback) {

        // Check if browser is capable of making cross-origin Ajax calls
        if(mangoPay._browser.corsSupport()) {
            mangoPay.cardRegistration.sendDataWithAjax(ajaxUrl, data, resultCallback, errorCallback);
            return;
        }

        // Browser doesn't support CORS, use the form with page reload
        mangoPay.cardRegistration.sendDataWithRedirect(redirectUrl, data);

    },

    /**
     * Processes card registration and redirects browser to the given URL to capture result
     * Does not rely on browser's cross-origin Ajax support
     *
     * @param {string} redirectUrl Your page browser will be redirected to process the payment
     * @param {object} data Sensitive card details {cardNumber, cardExpirationDate, cardCvx}
     */
    sendDataWithRedirect : function(redirectUrl, data) {

        // Build the form and append to the document
        var form = document.createElement('form');
        form.setAttribute('action', mangoPay._cardRegisterData.cardRegistrationURL);
        form.setAttribute('method', 'post');
        form.setAttribute('style', 'display: none');
        document.getElementsByTagName('body')[0].appendChild(form);

        // Add card registration data to the form
        form.appendChild(mangoPay._getInputElement('data', mangoPay._cardRegisterData.preregistrationData));
        form.appendChild(mangoPay._getInputElement('accessKeyRef', mangoPay._cardRegisterData.accessKey));
        form.appendChild(mangoPay._getInputElement('cardNumber', data.cardNumber));
        form.appendChild(mangoPay._getInputElement('cardExpirationDate', data.cardExpirationDate));
        form.appendChild(mangoPay._getInputElement('cardCvx', data.cardCvx));
        form.appendChild(mangoPay._getInputElement('returnURL', redirectUrl));

        // Submit the form
        form.submit();

    }

  },

  /**
   * PRIVATE. Builds a hidden form field DOM element
   *
   * @param {string} name Field name
   * @param {string} value Field value
   */
  _getInputElement : function(name, value) {
      var input = document.createElement('input');
      input.setAttribute('type', 'hidden');
      input.setAttribute('name', name);
      input.setAttribute('value', value);
      return input;
  },

  /**
   * PRIVATE. Performs an asynchronous HTTP (Ajax) request
   *
   * @param {object} settings {type, crossDomain, url, data, success, error}
   */
  _ajax: function(settings) {

      // XMLHttpRequest object
      var xmlhttp = new XMLHttpRequest();

      // Put together input data as string
      var parameters = "";
      for(var key in settings.data) {
          parameters += (parameters.length > 0 ? '&' : '' ) + key + "=" + encodeURIComponent(settings.data[key]);
      }

      // URL to hit, with parameters added for GET request
      var url = settings.url;
      if (settings.type === "get") {
          url = settings.url + (settings.url.indexOf("?") > -1 ? '&' : '?') + parameters;
      }

      // Cross-domain requests in IE 7, 8 and 9 using XDomainRequest
      if (settings.crossDomain && !("withCredentials" in xmlhttp) && window.XDomainRequest) {
          xdr = new XDomainRequest();
          xdr.onerror = function(){ settings.error(xdr); };
          xdr.onload = function(){ settings.success(xdr.responseText); };
          xdr.open(settings.type, url);
          xdr.send(settings.type === "post" ? parameters : null);
          return;
      }

      // Attach success and error handlers
      xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4) {
           if (xmlhttp.status == 200) {
                settings.success(xmlhttp.responseText);
           } else {
                settings.error(xmlhttp, xmlhttp.status, xmlhttp.statusText);
           }
         }
      };

      // Open connection
      xmlhttp.open(settings.type, url, true);

      // Send extra header for POST request
      if (settings.type === "post") {
         xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
      }

      // Send data
      xmlhttp.send(settings.type === "post" ? parameters : null);

  },

  _browser : {

    /**
     * Returns true if browser is capable of making cross-origin Ajax calls
     */
    corsSupport : function() {

        // IE 10 and above, Firefox, Chrome, Opera etc.
        if ("withCredentials" in new XMLHttpRequest()) {
            return true;
        }

        // IE 8 and IE 9
        if (window.XDomainRequest) {
            return true;
        }

        return false;

    }

  }

};
<commit_msg>add th possibility to define a custom method to display mongopay error<commit_after>
//This method is used to force the month and year to be two digits
function pad(num, length) {
    var s = "00" + num;
    return s.substr(s.length - length);
}

// Action for button "Pay with Ajax or Redirect"
function payAjaxOrRedirect(ajaxUrl,
                           redirectUrl,
                           cardRegistrationURL,
                           preregistrationData,
                           accessKey,
                           successRedirect,
                           failureRedirect)
{

    $('#submit-button').attr('disabled', true);

    mangoPay.cardRegistration.init({
        cardRegistrationURL : cardRegistrationURL,
        preregistrationData : preregistrationData,
        accessKey : accessKey
    });

    // Collect sensitive card data from the form
    var month = $("[data-id='troopers_mangopay_card_expiry_month']").val();
    var year = $("[data-id='troopers_mangopay_card_expiry_year']").val();

    var cardData = {
        cardNumber : $("[data-id='troopers_mangopay_card_number']").val(),
        cardExpirationDate : pad(month, 2) + "" + pad(year, 2),
        cardCvx : pad($("[data-id='troopers_mangopay_ccv']").val(), 3)
    };

    // Process data
    mangoPay.cardRegistration.sendDataWithAjaxOrRedirect(
        // URL to capture response when CORS is available
        ajaxUrl,
        // URL to capture response when CORS is not available
        redirectUrl,
        // Card data
        cardData,
        // Result Ajax callback
        function(data) {
            var json = $.parseJSON(data);
            if (json.success) {
                if (json.hasOwnProperty("redirect")) {
                    window.location = json.redirect;
                } else {
                    window.location = successRedirect;
                }
            } else {
                if (json.message) {
                    var message = json.message;
                } else {
                    var message = 'Une erreur s\'est produite lors de votre réservation, veuillez vérifier vos informations et réessayer. Si l\'erreur persiste, n\'hésitez pas à contacter le support.';
                }
                if (typeof(mangopayAlert) !== 'undefined')
                {
                  mangopayAlert(message);
                }else{
                    $('#alert-container').empty();
                    var alert = '
\
                        <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>\
                        \
                        ' + message + '\

';
                    $('#alert-container').append(alert);
                }
                window.scrollTo(0, 0);
                $('#submit-button').attr('disabled', false);
            }

        },
        // Error ajax callback
        function(xhr, status, error){
            if (typeof(mangopayAlert) !== 'undefined')
            {
              mangopayAlert(message);
            }else{
                $('#alert-container').empty();
                var alert = '
\
                    <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>\
                    \
                    Une erreur s\'est produite lors de votre achat, veuillez vérifier vos informations et réessayer. Si l\'erreur persiste, n\'hésitez pas à contacter le support.\

';
                window.scrollTo(0, 0);
                $('#alert-container').append(alert);
            }
            $('#submit-button').attr('disabled', false);
        }
    );
}

var mangoPay = {

  cardRegistration : {
      _cardRegisterData: null,

    /**
     * Initialize card registration object
     *
     * @param {object} cardRegisterData Card pre-registration data {cardRegistrationURL, preregistrationData, accessKey}
     */
    init : function(cardRegisterData) {

        mangoPay._cardRegisterData = cardRegisterData;

    },

    /**
     * Processes card registration and sends the result to given URL asynchronously
     * Requires a browser that supports cross-origin Ajax calls
     *
     * @param {string} ajaxUrl Your page to load asynchronously to process the payment
     * @param {object} data Sensitive card details {cardNumber, cardExpirationDate, cardCvx}
     * @param {function} resultCallback A function to invoke when the call to given ajaxUrl succeeds
     * @param {function} errorCallback A function to invoke when the call to given ajaxUrl fails
     */
    sendDataWithAjax : function(ajaxUrl, data, resultCallback, errorCallback) {

        // Get Payline token
        mangoPay._ajax({

            // Payline expects POST
            type: "post",

            // Payline service URL
            url: mangoPay._cardRegisterData.cardRegistrationURL,

            // Force CORS
            crossDomain: true,

            // Sensitive card data plus pre-registration data and access key
            data: {
                data: mangoPay._cardRegisterData.preregistrationData,
                accessKeyRef: mangoPay._cardRegisterData.accessKey,
                cardNumber: data.cardNumber,
                cardExpirationDate: data.cardExpirationDate,
                cardCvx: data.cardCvx
            },

            // Forward response to the return URL
            success: function(data) {

                var dataToSend = "";

                // Prepare data
                if (data === null ) {
                    dataToSend = { errorCode: '' };
                } else if (data.indexOf("data=") === 0) {
                    dataToSend = { data: data.replace("data=", "") };
                } else {
                    dataToSend = { errorCode: data.replace("errorCode=", "") };
                }

                // Send data to the return page
                mangoPay._ajax({
                    type: "get",
                    url: ajaxUrl,
                    data: dataToSend,
                    success: resultCallback,
                    error: errorCallback
                });

            },

            error: errorCallback

        });
    },

    /**
     * Processes card registration and sends the result to given URL asynchronously or redirects browser to the given URL to capture result
     * Automatically detects if browser is capable of making cross-origin Ajax calls
     *
     * @param {string} ajaxUrl Your page to call asynchronously to process the payment
     * @param {string} redirectUrl Your page browser will be redirected to process the payment
     * @param {object} data Sensitive card details {cardNumber, cardExpirationDate, cardCvx}
     * @param {function} resultCallback A function to invoke when the call to given ajaxUrl succeeds
     * @param {function} errorCallback A function to invoke when the call to given ajaxUrl fails
     */
    sendDataWithAjaxOrRedirect: function(ajaxUrl, redirectUrl, data, resultCallback, errorCallback) {

        // Check if browser is capable of making cross-origin Ajax calls
        if(mangoPay._browser.corsSupport()) {
            mangoPay.cardRegistration.sendDataWithAjax(ajaxUrl, data, resultCallback, errorCallback);
            return;
        }

        // Browser doesn't support CORS, use the form with page reload
        mangoPay.cardRegistration.sendDataWithRedirect(redirectUrl, data);

    },

    /**
     * Processes card registration and redirects browser to the given URL to capture result
     * Does not rely on browser's cross-origin Ajax support
     *
     * @param {string} redirectUrl Your page browser will be redirected to process the payment
     * @param {object} data Sensitive card details {cardNumber, cardExpirationDate, cardCvx}
     */
    sendDataWithRedirect : function(redirectUrl, data) {

        // Build the form and append to the document
        var form = document.createElement('form');
        form.setAttribute('action', mangoPay._cardRegisterData.cardRegistrationURL);
        form.setAttribute('method', 'post');
        form.setAttribute('style', 'display: none');
        document.getElementsByTagName('body')[0].appendChild(form);

        // Add card registration data to the form
        form.appendChild(mangoPay._getInputElement('data', mangoPay._cardRegisterData.preregistrationData));
        form.appendChild(mangoPay._getInputElement('accessKeyRef', mangoPay._cardRegisterData.accessKey));
        form.appendChild(mangoPay._getInputElement('cardNumber', data.cardNumber));
        form.appendChild(mangoPay._getInputElement('cardExpirationDate', data.cardExpirationDate));
        form.appendChild(mangoPay._getInputElement('cardCvx', data.cardCvx));
        form.appendChild(mangoPay._getInputElement('returnURL', redirectUrl));

        // Submit the form
        form.submit();

    }

  },

  /**
   * PRIVATE. Builds a hidden form field DOM element
   *
   * @param {string} name Field name
   * @param {string} value Field value
   */
  _getInputElement : function(name, value) {
      var input = document.createElement('input');
      input.setAttribute('type', 'hidden');
      input.setAttribute('name', name);
      input.setAttribute('value', value);
      return input;
  },

  /**
   * PRIVATE. Performs an asynchronous HTTP (Ajax) request
   *
   * @param {object} settings {type, crossDomain, url, data, success, error}
   */
  _ajax: function(settings) {

      // XMLHttpRequest object
      var xmlhttp = new XMLHttpRequest();

      // Put together input data as string
      var parameters = "";
      for(var key in settings.data) {
          parameters += (parameters.length > 0 ? '&' : '' ) + key + "=" + encodeURIComponent(settings.data[key]);
      }

      // URL to hit, with parameters added for GET request
      var url = settings.url;
      if (settings.type === "get") {
          url = settings.url + (settings.url.indexOf("?") > -1 ? '&' : '?') + parameters;
      }

      // Cross-domain requests in IE 7, 8 and 9 using XDomainRequest
      if (settings.crossDomain && !("withCredentials" in xmlhttp) && window.XDomainRequest) {
          xdr = new XDomainRequest();
          xdr.onerror = function(){ settings.error(xdr); };
          xdr.onload = function(){ settings.success(xdr.responseText); };
          xdr.open(settings.type, url);
          xdr.send(settings.type === "post" ? parameters : null);
          return;
      }

      // Attach success and error handlers
      xmlhttp.onreadystatechange = function() {
        if (xmlhttp.readyState == 4) {
           if (xmlhttp.status == 200) {
                settings.success(xmlhttp.responseText);
           } else {
                settings.error(xmlhttp, xmlhttp.status, xmlhttp.statusText);
           }
         }
      };

      // Open connection
      xmlhttp.open(settings.type, url, true);

      // Send extra header for POST request
      if (settings.type === "post") {
         xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
      }

      // Send data
      xmlhttp.send(settings.type === "post" ? parameters : null);

  },

  _browser : {

    /**
     * Returns true if browser is capable of making cross-origin Ajax calls
     */
    corsSupport : function() {

        // IE 10 and above, Firefox, Chrome, Opera etc.
        if ("withCredentials" in new XMLHttpRequest()) {
            return true;
        }

        // IE 8 and IE 9
        if (window.XDomainRequest) {
            return true;
        }

        return false;

    }

  }

};
<|endoftext|>


<commit_before>foam.CLASS({
  package: 'foam.doc',
  name: 'DocBorder',
  extends: 'foam.u2.Element',

  axioms: [
    foam.u2.CSS.create({
      code: function() {/*
        ^ {
             display: inline-block;
             border-radius: 3px;
             box-shadow: 0 1px 3px rgba(0, 0, 0, 0.38);
        }
        ^title { padding: 6px; align-content: center; background: #c8e2f9; }
        ^info { float: right; font-size: smaller; }
        ^content { padding: 6px; min-width: 220px; height: 100%; background: white; }
      */}
    })
  ],

  properties: [
    'title',
    'info'
  ],

  methods: [
    function init() {
      this.
        cssClass(this.myCls()).
        start('div').
          cssClass(this.myCls('title')).
          add(this.title$).
          start('span').
            cssClass(this.myCls('info')).
            add(this.info$).
          end().
        end().
        start('div', null, this.content$).
          cssClass(this.myCls('content')).
        end();
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'AxiomInfo',
  ids: ['name'],

  requires: [
    'foam.doc.ClassLink'
  ],

  properties: [
    {
      name: 'axiom',
      hidden: true
    },
    {
      name: 'cls',
      label: 'Source Class',
      tableCellView: function(o, e) {
        return foam.doc.LinkView.create({data: o.cls}, e.__subSubContext__);
      },
      tableCellFormatter: function(value, obj, axiom) {
        this.tag(foam.doc.LinkView, { data: value });
      }
    },
    {
      name: 'type',
      tableCellView: function(o, e) {
        return o.type ?
          foam.doc.LinkView.create({data: foam.doc.Link.create({path: o.type.id, label: o.type.name})}, e.__subSubContext__) :
          'anonymous';
      },
      tableCellFormatter: function(value, obj, axiom) {
        if ( value ) {
          this.tag(foam.doc.LinkView, { data: foam.doc.Link.create({ path: value.id, label: value.name }) });
          return;
        }
        this.add('anonymous');
      }
    },
    {
      name: 'name',
      tableCellFormatter: function(value, obj, axiom) {
        if ( obj.type === foam.core.Requires ) {
          this.tag(obj.ClassLink, {data: obj.axiom.path, showPackage: true});
        } else if ( obj.type === foam.core.Implements ) {
          this.tag(obj.ClassLink, {data: obj.axiom.path, showPackage: true});
        } else {
          this.add(value);
        }
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'ClassList',
  extends: 'foam.u2.View',

  requires: [
    'foam.doc.DocBorder',
    'foam.doc.ClassLink'
  ],

  properties: [
    'title',
    {
      name: 'info',
      expression: function (data) {
        return data && data.length;
      }
    }
  ],

  methods: [
    function initE() {
      this.SUPER();
      var self = this;
      this.
        start(this.DocBorder, {title: this.title, info$: this.info$}).
          start('div').
            add(this.slot(function (data) {
              return self.E('span').forEach(data, function(d) { this.tag(self.ClassLink, {data: d, showPackage: true}).br(); });
            })).
          end().
        end();
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'ClassDocView',
  extends: 'foam.u2.View',

  requires: [
    'foam.doc.Link',
    'foam.doc.ClassLink',
    'foam.doc.AxiomInfo',
    'foam.u2.view.TableView',
    'foam.dao.ArrayDAO'
  ],

  imports: [
    'selectedAxiom',
    'showInherited'
  ],

  methods: [
    function initE() {
      this.SUPER();

      var data = this.data;

      this.
          start('b').add(data.id).end().
          start('span').style({float:'right','font-size':'smaller'}).add(data.count_, ' created').end().br().
          add('extends: ');

      var cls = data;
      for ( var i = 0 ; cls ; i++ ) {
        cls = this.lookup(cls.model_.extends, true);
        if ( i ) this.add(' : ');
        this.start(this.ClassLink, {data: cls}).end();
        if ( cls === foam.core.FObject ) break;
      }
      this.br();
      this.add(data.documentation);

      this.add(this.slot(function (showInherited) {
        // TODO: hide 'Source Class' column if showInherited is false
        var axs = [];
        for ( var key in data.axiomMap_ ) {
          if ( showInherited || Object.hasOwnProperty.call(data.axiomMap_, key) ) {
            var a  = data.axiomMap_[key];
            var ai = foam.doc.AxiomInfo.create({
              axiom: a,
              type: a.cls_,
              cls: this.Link.create({
                path: a.sourceCls_.id,
                label: a.sourceCls_.name
              }),
              name: a.name
            });
            axs.push(ai);
          }
        }

        return this.TableView.create({
          of: this.AxiomInfo,
          data: this.ArrayDAO.create({array: axs}),
          hoverSelection$: this.selectedAxiom$
        });
      }));
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'Link',

  properties: [
    'path',
    'label'
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'LinkView',
  extends: 'foam.u2.View',

  imports: [ 'browserPath' ],

  methods: [
    function initE() {
      this.SUPER();

      this.setNodeName('a').
        on('click', this.click).
        attrs({href: this.data.path}).
        add(this.data.label);
    }
  ],

  listeners: [
    function click(e) {
      this.browserPath$.set(this.data.path);
      e.preventDefault();
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'ClassLink',
  extends: 'foam.u2.View',

  imports: [ 'browserPath' ],

  properties: [
    {
      class: 'Class',
      name: 'data'
    },
    {
      class: 'Boolean',
      name: 'showPackage'
    }
  ],

  methods: [
    function initE() {
      this.SUPER();

      this.setNodeName('a').
        on('click', this.click).
        attrs({href: this.data.id}).
        add(this.showPackage ? this.data.id : this.data.name);
    }
  ],

  listeners: [
    function click(e) {
      this.browserPath$.set(this.data.id);
      e.preventDefault();
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'DocBrowser',
  extends: 'foam.u2.Element',

  requires: [
    'foam.doc.DocBorder',
    'foam.doc.ClassList',
    'foam.doc.ClassDocView'
  ],

  exports: [
    'as data',
    'path as browserPath',
    'axiom as selectedAxiom',
    'showInherited'
  ],

  properties: [
    'path',
    {
      name: 'selectedClass',
      expression: function (path) {
        return foam.lookup(path, true);
      }
    },
    {
      class: 'Boolean',
      name: 'showInherited',
      value: true
    },
    {
      class: 'FObjectProperty',
      name: 'axiom',
      view: { class: 'foam.u2.DetailView' }
    },
    {
      name: 'subClasses',
      expression: function (path) {
        return Object.values(foam.USED).
            filter(function(cls) { return cls.model_.extends == path || 'foam.core.' + cls.model_.extends == path; }).
            sort(foam.core.Model.ID.compare);
      }
    },
    {
      name: 'requiredByClasses',
      expression: function (path) {
        return Object.values(foam.USED).
            filter(function(cls) {
              return cls.model_.requires && cls.model_.requires.map(
                  function(r) { return r.path; }).includes(path);
            }).
            sort(foam.core.Model.ID.compare);
      }
    },
    {
      name: 'relationshipClasses',
      expression: function (path) {
        return [];
      }
    },
    'subClassCount'
  ],

  methods: [
    function initE() {
      this.SUPER();

      this.
        tag(this.PATH, {displayWidth: 80}).
          start('span').
            style({'margin-left': '12px', 'font-size':'small'}).
            add('  Show Inherited Axioms: ').
          end().
          tag(this.SHOW_INHERITED, {data$: this.showInherited$}).
        br().br().
        start('table').
          start('tr').
            start('td').
              style({'vertical-align': 'top'}).
              tag(this.ClassList, {title: 'Class List', data: Object.values(foam.USED).sort(foam.core.Model.ID.compare)}).
            end().
            start('td').
              style({'vertical-align': 'top'}).
          start(this.DocBorder, {title: 'Class Definition', info$: this.slot(function(selectedClass) { return selectedClass.getOwnAxioms().length + ' / ' + selectedClass.getAxioms().length; })}).
                add(this.slot(function(selectedClass) {
                  if ( ! selectedClass ) return '';
                  return this.ClassDocView.create({data: selectedClass});
                })).
              end().
            end().
            start('td').
              style({'vertical-align': 'top'}).
              tag(this.ClassList, {title: 'Sub-Classes', data$: this.subClasses$}).
              br().
              tag(this.ClassList, {title: 'Required-By', data$: this.requiredByClasses$}).
              br().
              tag(this.ClassList, {title: 'Relationships', data$: this.relationshipClasses$}).
            end().
            start('td').
              style({'vertical-align': 'top'}).
              start(this.DocBorder, {title: 'Axiom Definition'}).
                add(this.slot(function (axiom) { return axiom && foam.u2.DetailView.create({data: axiom.axiom}); })).
              end().
            end().
          end().
        end();
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'DocBrowserWindow',

  requires: [
    'foam.doc.DocBrowser',
    'foam.core.Window'
  ],

  imports: [ 'window' ],

  properties: [
    'initialClass'
  ],

  methods: [
    function init() {
      // TODO: There should be some helper support to make this easier
      var w = this.window.open('', '', 'width=700, heigh=1000');
      var window = foam.core.Window.create({window: w});
      var browser = this.DocBrowser.create({path: this.initialClass}, window.__subContext__);
      w.document.body.insertAdjacentHTML('beforeend', browser.outerHTML);
      browser.load();
    }
  ]
});

foam.debug.doc = function(opt_obj, showUnused) {
  if ( showUnused ) {
    for ( var key in foam.UNUSED ) foam.lookup(key);
  }

  foam.doc.DocBrowserWindow.create({
    initialClass: foam.core.FObject.isSubClass(opt_obj) ?
      opt_obj.id :
      ( opt_obj && opt_obj.cls_ ) ? opt_obj.cls_.id :
      'foam.core.FObject' });
};
<commit_msg>DocBrowser.<commit_after>foam.CLASS({
  package: 'foam.doc',
  name: 'DocBorder',
  extends: 'foam.u2.Element',

  axioms: [
    foam.u2.CSS.create({
      code: function() {/*
        ^ {
             border-radius: 3px;
             box-shadow: 0 1px 3px rgba(0, 0, 0, 0.38);
             display: inline-block;
             width:100%;
        }
        ^title { padding: 6px; align-content: center; background: #c8e2f9; }
        ^info { float: right; font-size: smaller; }
        ^content { padding: 6px; min-width: 220px; height: 100%; background: white; }
      */}
    })
  ],

  properties: [
    'title',
    'info'
  ],

  methods: [
    function init() {
      this.
        cssClass(this.myCls()).
        start('div').
          cssClass(this.myCls('title')).
          add(this.title$).
          start('span').
            cssClass(this.myCls('info')).
            add(this.info$).
          end().
        end().
        start('div', null, this.content$).
          cssClass(this.myCls('content')).
        end();
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'AxiomInfo',
  ids: ['name'],

  requires: [
    'foam.doc.ClassLink'
  ],

  properties: [
    {
      name: 'axiom',
      hidden: true
    },
    {
      name: 'cls',
      label: 'Source Class',
      tableCellView: function(o, e) {
        return foam.doc.LinkView.create({data: o.cls}, e.__subSubContext__);
      },
      tableCellFormatter: function(value, obj, axiom) {
        this.tag(foam.doc.LinkView, { data: value });
      }
    },
    {
      name: 'type',
      tableCellView: function(o, e) {
        return o.type ?
          foam.doc.LinkView.create({data: foam.doc.Link.create({path: o.type.id, label: o.type.name})}, e.__subSubContext__) :
          'anonymous';
      },
      tableCellFormatter: function(value, obj, axiom) {
        if ( value ) {
          this.tag(foam.doc.LinkView, { data: foam.doc.Link.create({ path: value.id, label: value.name }) });
          return;
        }
        this.add('anonymous');
      }
    },
    {
      name: 'name',
      tableCellFormatter: function(value, obj, axiom) {
        if ( obj.type === foam.core.Requires ) {
          this.tag(obj.ClassLink, {data: obj.axiom.path, showPackage: true});
        } else if ( obj.type === foam.core.Implements ) {
          this.tag(obj.ClassLink, {data: obj.axiom.path, showPackage: true});
        } else {
          this.add(value);
        }
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'ClassList',
  extends: 'foam.u2.View',

  requires: [
    'foam.doc.DocBorder',
    'foam.doc.ClassLink'
  ],

  properties: [
    'title',
    {
      name: 'info',
      expression: function (data) {
        return data && data.length;
      }
    }
  ],

  methods: [
    function initE() {
      this.SUPER();
      var self = this;
      this.
        start(this.DocBorder, {title: this.title, info$: this.info$}).
          start('div').
            add(this.slot(function (data) {
              return self.E('span').forEach(data, function(d) { this.tag(self.ClassLink, {data: d, showPackage: true}).br(); });
            })).
          end().
        end();
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'ClassDocView',
  extends: 'foam.u2.View',

  requires: [
    'foam.doc.Link',
    'foam.doc.ClassLink',
    'foam.doc.AxiomInfo',
    'foam.u2.view.TableView',
    'foam.dao.ArrayDAO'
  ],

  imports: [
    'selectedAxiom',
    'showInherited'
  ],

  methods: [
    function initE() {
      this.SUPER();

      var data = this.data;

      this.
          start('b').add(data.id).end().
          start('span').style({float:'right','font-size':'smaller'}).add(data.count_, ' created').end().br().
          add('extends: ');

      var cls = data;
      for ( var i = 0 ; cls ; i++ ) {
        cls = this.lookup(cls.model_.extends, true);
        if ( i ) this.add(' : ');
        this.start(this.ClassLink, {data: cls}).end();
        if ( cls === foam.core.FObject ) break;
      }
      this.br();
      this.add(data.documentation);

      this.add(this.slot(function (showInherited) {
        // TODO: hide 'Source Class' column if showInherited is false
        var axs = [];
        for ( var key in data.axiomMap_ ) {
          if ( showInherited || Object.hasOwnProperty.call(data.axiomMap_, key) ) {
            var a  = data.axiomMap_[key];
            var ai = foam.doc.AxiomInfo.create({
              axiom: a,
              type: a.cls_,
              cls: this.Link.create({
                path: a.sourceCls_.id,
                label: a.sourceCls_.name
              }),
              name: a.name
            });
            axs.push(ai);
          }
        }

        return this.TableView.create({
          of: this.AxiomInfo,
          data: this.ArrayDAO.create({array: axs}),
          hoverSelection$: this.selectedAxiom$
        });
      }));
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'Link',

  properties: [
    'path',
    'label'
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'LinkView',
  extends: 'foam.u2.View',

  imports: [ 'browserPath' ],

  methods: [
    function initE() {
      this.SUPER();

      this.setNodeName('a').
        on('click', this.click).
        attrs({href: this.data.path}).
        add(this.data.label);
    }
  ],

  listeners: [
    function click(e) {
      this.browserPath$.set(this.data.path);
      e.preventDefault();
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'ClassLink',
  extends: 'foam.u2.View',

  imports: [ 'browserPath' ],

  properties: [
    {
      class: 'Class',
      name: 'data'
    },
    {
      class: 'Boolean',
      name: 'showPackage'
    }
  ],

  methods: [
    function initE() {
      this.SUPER();

      this.setNodeName('a').
        on('click', this.click).
        attrs({href: this.data.id}).
        add(this.showPackage ? this.data.id : this.data.name);
    }
  ],

  listeners: [
    function click(e) {
      this.browserPath$.set(this.data.id);
      e.preventDefault();
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'DocBrowser',
  extends: 'foam.u2.Element',

  requires: [
    'foam.doc.DocBorder',
    'foam.doc.ClassList',
    'foam.doc.ClassDocView'
  ],

  exports: [
    'as data',
    'path as browserPath',
    'axiom as selectedAxiom',
    'showInherited'
  ],

  properties: [
    'path',
    {
      name: 'selectedClass',
      expression: function (path) {
        return foam.lookup(path, true);
      }
    },
    {
      class: 'Boolean',
      name: 'showInherited',
      value: true
    },
    {
      class: 'FObjectProperty',
      name: 'axiom',
      view: { class: 'foam.u2.DetailView' }
    },
    {
      name: 'subClasses',
      expression: function (path) {
        return Object.values(foam.USED).
            filter(function(cls) { return cls.model_.extends == path || 'foam.core.' + cls.model_.extends == path; }).
            sort(foam.core.Model.ID.compare);
      }
    },
    {
      name: 'requiredByClasses',
      expression: function (path) {
        return Object.values(foam.USED).
            filter(function(cls) {
              return cls.model_.requires && cls.model_.requires.map(
                  function(r) { return r.path; }).includes(path);
            }).
            sort(foam.core.Model.ID.compare);
      }
    },
    {
      name: 'relationshipClasses',
      expression: function (path) {
        return [];
      }
    },
    'subClassCount'
  ],

  methods: [
    function initE() {
      this.SUPER();

      this.
        tag(this.PATH, {displayWidth: 80}).
          start('span').
            style({'margin-left': '12px', 'font-size':'small'}).
            add('  Show Inherited Axioms: ').
          end().
          tag(this.SHOW_INHERITED, {data$: this.showInherited$}).
        br().br().
        start('table').
          start('tr').
            start('td').
              style({'vertical-align': 'top'}).
              tag(this.ClassList, {title: 'Class List', data: Object.values(foam.USED).sort(foam.core.Model.ID.compare)}).
            end().
            start('td').
              style({'vertical-align': 'top'}).
          start(this.DocBorder, {title: 'Class Definition', info$: this.slot(function(selectedClass) { return selectedClass.getOwnAxioms().length + ' / ' + selectedClass.getAxioms().length; })}).
                add(this.slot(function(selectedClass) {
                  if ( ! selectedClass ) return '';
                  return this.ClassDocView.create({data: selectedClass});
                })).
              end().
            end().
            start('td').
              style({'vertical-align': 'top'}).
              tag(this.ClassList, {title: 'Sub-Classes', data$: this.subClasses$}).
              br().
              tag(this.ClassList, {title: 'Required-By', data$: this.requiredByClasses$}).
              br().
              tag(this.ClassList, {title: 'Relationships', data$: this.relationshipClasses$}).
            end().
            start('td').
              style({'vertical-align': 'top'}).
              start(this.DocBorder, {title: 'Axiom Definition'}).
                add(this.slot(function (axiom) { return axiom && foam.u2.DetailView.create({data: axiom.axiom}); })).
              end().
            end().
          end().
        end();
    }
  ]
});

foam.CLASS({
  package: 'foam.doc',
  name: 'DocBrowserWindow',

  requires: [
    'foam.doc.DocBrowser',
    'foam.core.Window'
  ],

  imports: [ 'window' ],

  properties: [
    'initialClass'
  ],

  methods: [
    function init() {
      // TODO: There should be some helper support to make this easier
      var w = this.window.open('', '', 'width=700, heigh=1000');
      var window = foam.core.Window.create({window: w});
      var browser = this.DocBrowser.create({path: this.initialClass}, window.__subContext__);
      w.document.body.insertAdjacentHTML('beforeend', browser.outerHTML);
      browser.load();
    }
  ]
});

foam.debug.doc = function(opt_obj, showUnused) {
  if ( showUnused ) {
    for ( var key in foam.UNUSED ) foam.lookup(key);
  }

  foam.doc.DocBrowserWindow.create({
    initialClass: foam.core.FObject.isSubClass(opt_obj) ?
      opt_obj.id :
      ( opt_obj && opt_obj.cls_ ) ? opt_obj.cls_.id :
      'foam.core.FObject' });
};
<|endoftext|>


<commit_before>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commit_time_rem = commit_time - (commit_time_hour * 3600)
    var commit_time_min = Math.floor(commit_time_rem / 60)
    var commit_time_sec = commit_time_rem - (commit_time_min * 60)
    console.info("Input file is %s Bytes, this will generate %s commits and take approximately %s hours %s minutes %s seconds", length, commit_count, commit_time_hour, commit_time_min, commit_time_sec)
    var t_offset = 0
    if (process.env.FAKETIME) {
      // 20% buffer, to reduce the likelihood of going in to the future
      t_offset = commit_time * -1.2;
      faketime(t_offset);
    }
    try {
      child_process.execFileSync('git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var counter = 0
    process.stdout.write("Queueing up the first commit...\r");
    var timeout;
    if (process.env.FAKETIME) {
      faketime(t_offset);
      timeout = 20;
    } else {
      timeout = randomIntFromInterval(0, max_sleep) * 1000
    }
    setTimeout(commit, timeout, t_offset, outFD, outFile, data, counter, length);
  })
} else {
  console.info("Usage:")
  console.info("node commit.js infile outfile [max_time_in_seconds] [step]")
}

function sleep(seconds) {
  var endTime = new Date().getTime() + (seconds * 1000);
  while (new Date().getTime() <= endTime) {;}
}

function randomIntFromInterval(min,max)
{
   return Math.floor(Math.random()*(max-min+1)+min);
}

function commit(t_offset, outFD, outFile, <commit_msg>Fixing punctuation<commit_after>var child_process = require('child_process')
var fs = require('fs');
var max_sleep = 300
var step = 10
//Added a comment that achieves no real goal.
//Non-blocking loop
//Adjustable step
//Status line
//Add a rough time indicator
//First cut at libfaketime support

var commit_messages = [
  "Fixing an important issue with the universe.",
  "Someone poisoned the waterhole!",
  "You feeling lucky punk?",
  "Five bullets or six?",
  "Fixed memory parsing error #1337",
  "Cleaned out the intertubes",
  "AAAAAAAAAAARGH!",
  "Fixed a typo",
  "Updated the readme",
  "Fixing a typo added in the last readme update",
  "GET A HAIRCUT!",
  "Updated the readme again",
  "Found an issue with the letter 'a', so I fixed it.",
  "Incompatible dimensions found, Cthuhlu Error 666",
  "Who you calling a fool?",
  "How many more of these can I make?",
  "Fixing an error introduced in the last commit",
  "Re-updating the readme.",
  "Work in Progress",
  "WIP",
  "Quick fix",
  "Grammar fix",
  "Fixing punctuation",
  "Correcting style",
  "Logic error",
  "Almost there",
  "Nearly got it",
  "Not quite working",
  "Ooops!",
  "Did I do that?",
  "Commit all the required changes",
  "Really commit all the required changes",
  "Should work now",
  "Back out the last commit",
  "Reverting changes",
  "One more time...",
  "Re-commiting last",
  "One more User Story done",
  "Can work my way through the Kanban",
  "Sprint complete",
  "Well that seemed pretty easy",
  "What do you mean you can't pack up the commit?",
  "Merge in master",
  "Fast-forwarding changes"
]

if ( process.argv[ 2 ] && process.argv[ 3 ] ) {
  var inFile = process.argv[ 2 ]
  var outFile = process.argv[ 3 ]
  if (inFile == outFile) {
    console.error("Aborted: infile and outfile must be different")
    return(-1);
  }
  if (process.argv [ 4 ]) max_sleep = process.argv [ 4 ]
  if (process.argv [ 5 ]) step = parseInt(process.argv [ 5 ])
  console.info("Writing from %s to %s, with up to %s seconds between commits of %s bytes", inFile, outFile, max_sleep, step)
  var outFD = fs.openSync(outFile, 'w')
  fs.readFile(inFile, function(err,data) {
    var length = data.length
    var commit_count = Math.ceil(length / step)
    var commit_time = commit_count * max_sleep / 2
    var commit_time_hour = Math.floor(commit_time / 3600)
    var commit_time_rem = commit_time - (commit_time_hour * 3600)
    var commit_time_min = Math.floor(commit_time_rem / 60)
    var commit_time_sec = commit_time_rem - (commit_time_min * 60)
    console.info("Input file is %s Bytes, this will generate %s commits and take approximately %s hours %s minutes %s seconds", length, commit_count, commit_time_hour, commit_time_min, commit_time_sec)
    var t_offset = 0
    if (process.env.FAKETIME) {
      // 20% buffer, to reduce the likelihood of going in to the future
      t_offset = commit_time * -1.2;
      faketime(t_offset);
    }
    try {
      child_process.execFileSync('git', ['add', outFile])
    } catch (e) {
      console.error("Couldn't add %s to git: %s", outFile, e)
    }
    var counter = 0
    process.stdout.write("Queueing up the first commit...\r");
    var timeout;
    if (process.env.FAKETIME) {
      faketime(t_offset);
      timeout = 20;
    } else {
      timeout = randomIntFromInterval(0, max_sleep) * 1000
    }
    setTimeout(commit, timeout, t_offset, outFD, outFile, data, counter, length);
  })
} else {
  console.info("Usage:")
  console.info("node commit.js infile outfile [max_time_in_seconds] [step]")
}

function sleep(seconds) {
  var endTime = new Date().getTime() + (seconds * 1000);
  while (new Date().getTime() <= endTime) {;}
}

function randomIntFromInterval(min,max)
{
   return Math.floor(Math.random()*(max-min+1)+min);
}

function commit(t_offset, outFD, outFile, d<|endoftext|>


<commit_before>'use strict';

var express = require('express');
var routes = require('./app/routes/index.js');
var mongoose = require('mongoose');
var passport = require('passport');
var Strategy = require('passport-facebook').Strategy;
var Users = require('./app/models/users.js');
var Books = require('./app/models/books.js');
var gBooks = require ('google-books-search');
var multer  = require('multer')
var upload = multer({ dest: 'uploads/' })

var session = require('express-session');
require('dotenv').load();
var app = express();

mongoose.connect(process.env.MONGO_URI);

//configure passport

passport.use(new Strategy({
    clientID: process.env.FACEBOOK_KEY,
    clientSecret: process.env.FACEBOOK_SECRET,
    callbackURL: "https://fcc-booktrader-jessjo.c9users.io/auth/facebook/callback"
  },
  function(accessToken, refreshToken, profile, cb) {

        //check user table for anyone with a facebook ID of profile.id
        Users.findOne({
            'id': profile.id
        }, function(err, user) {
            if (err) {
                return cb(err);
            }
            //No user was found... so create a new user with values from Facebook (all the profile. stuff)
            if (!user) {
            	console.log(profile);
                user = new Users({
                	id:profile.id,
                    name: profile.displayName,
                    username: profile.username,

                });
                user.save(function(err) {
                    if (err) console.log(err);
                    return cb(err, user);
                });
            } else {
                //found user. Return
                return cb(err, user);
            }
        });
    }

));

app.set('views', __dirname + '/app/views');
app.set('view engine', 'ejs');
app.use(session({ secret: 'ilovebunnyrabbits' }));
app.use(passport.initialize());
app.use(passport.session());

app.get('/',
  function(req, res) {
    res.render('index', { user: req.user, search: "", book: "", owned: "" });

  });

  app.get('/login',
  function(req, res){
    res.render('login');
  });

  app.get('/mybooks',
  function(req, res) {
    var books = [];
    //find a user, get their book list.

    //look up each book add to book array
    console.log(req.user);
        var z =0;
    		for (var i=0; i<req.user.books.length; i++){

    		  Books.findOne({
            		  'bookid': req.user.books[i]
        		  }, function(err, book) {
            	  	if (err) {
                	  	return err;
            	  	}
            	  	if (book){
            	  	  books[z] = book;
            	  	  z++;
            	  	}
            	  	if (i == req.user.books.length){
            	  	    console.log (books);
            	        res.render('mybooks', { user: req.user, books: books });
            	  	  }
        		});
    		}

  });

  app.post('/findBook', upload.array(),
  	function(req,res){
  		console.log(req.body.title);

  		//set to only return 1 best match book

  	    var options = {
    		field: 'title',
    		offset: 0,
 			limit: 1,
    		type: 'books',
    		order: 'relevance',
    		lang: 'en'
		};

    	var thisBook = gBooks.search(req.body.title, options, function(error, results) {
    			if ( ! error ) {
     			console.log(results);
     			//book found in google books api, search our data base to see if it exists or add

     			Books.findOne({
            		'bookid': results[0].id
        		}, function(err, book) {
            		if (err) {
                		return err;
            		}
            		//no book found, create one.
        			 if (!book) {

                		book = new Books({
                			bookid:results[0].id,
                	 		title: results[0].title,
                	 	    author: results[0].authors,
                    		rating: results[0].averageRating,
                    		thumbnail: results[0].thumbnail,

                		});
                	book.save(function(err) {
                    	if (err) console.log(err);
                    	console.log(book);

                    	res.render('index', { user: req.user, search: req.body.title, book: book, owned: "" });
                    	return book;

                	});

            	} else {
                	//found book. Return. The only time to check if owned is if we know it's in collection.

                	console.log("found book");
                	console.log(book);
                	var owned = false;
                	if (req.user){
                		console.log(req.user);
                		owned = checkOwnership(book.bookid, req.user, res, req, book, owned);
                	} else {
                		console.log ("the owned status is "+ owned);
                		res.render('index', { user: req.user, search: req.body.title, book: book, owned: owned });
          				return book;
                	}
            }
        });

    		} else {
        		console.log(error);
        		//what to do if error in searching for book
        		res.render('index', { user: req.user, search: req.body.title, book: "", owned: "" });
    		}
		});

  })

  app.post('/addBook', upload.array(),
  	 function(req,res){
  	 	var user = req.user;
  	 	var thisBookID = req.body.bookID;
  			   	Books.findOneAndUpdate(
    					{bookid: req.body.bookID},
    					{$push: {owners: user.id}},
    					{safe: true, upsert: true},
    					function(err, model) {
        					if (err) console.log(err);
			                	Users.findOneAndUpdate(
			    					{id: user.id},
			    					{$push: {books: thisBookID}},
			    					{safe: true, upsert: true},
			    					function(err, model2) {
			    						console.log ("user update:" + model2)
			    						console.log(user);
			        					if (err) console.log(err);
			        					res.render('index', { user: user, search: req.body.title, book: "", owned: true });

			    					}
			    				);

			    					}
			    	);

        		});

passport.serializeUser(function(user, cb) {
  cb(null, user);
});

passport.deserializeUser(function(obj, cb) {
  cb(null, obj);
});

app.get('/auth/facebook',
  passport.authenticate('facebook'));

app.get('/auth/facebook/callback',
  passport.authenticate('facebook', { failureRedirect: '/login' }),
  function(req, res) {
    // Successful authentication, redirect home.
    res.redirect('/');
  });

var port = process.env.PORT || 8080;
app.listen(port,  function () {
	console.log('Node.js listening on port ' + port + '...');
});

//function to check if the user owns a given book
function checkOwnership(bookID, user, res, req, book, owned){
	console.log(bookID + " is the bookID");
	console.log(user.books.indexOf(bookID) + " is the index of bookID");
	if(user.books.indexOf(bookID) >= 0){

		owned = true;
		console.log ("the owned status is "+ owned);
        res.render('index', { user: req.user, search: req.body.title, book: book, owned: owned });

	} else {
		 res.render('index', { user: req.user, search: req.body.title, book: book, owned: owned });

	}

}<commit_msg>logic fixed<commit_after>'use strict';

var express = require('express');
var routes = require('./app/routes/index.js');
var mongoose = require('mongoose');
var passport = require('passport');
var Strategy = require('passport-facebook').Strategy;
var Users = require('./app/models/users.js');
var Books = require('./app/models/books.js');
var gBooks = require ('google-books-search');
var multer  = require('multer')
var upload = multer({ dest: 'uploads/' })

var session = require('express-session');
require('dotenv').load();
var app = express();

mongoose.connect(process.env.MONGO_URI);

//configure passport

passport.use(new Strategy({
    clientID: process.env.FACEBOOK_KEY,
    clientSecret: process.env.FACEBOOK_SECRET,
    callbackURL: "https://fcc-booktrader-jessjo.c9users.io/auth/facebook/callback"
  },
  function(accessToken, refreshToken, profile, cb) {

        //check user table for anyone with a facebook ID of profile.id
        Users.findOne({
            'id': profile.id
        }, function(err, user) {
            if (err) {
                return cb(err);
            }
            //No user was found... so create a new user with values from Facebook (all the profile. stuff)
            if (!user) {
            	console.log(profile);
                user = new Users({
                	id:profile.id,
                    name: profile.displayName,
                    username: profile.username,

                });
                user.save(function(err) {
                    if (err) console.log(err);
                    return cb(err, user);
                });
            } else {
                //found user. Return
                return cb(err, user);
            }
        });
    }

));

app.set('views', __dirname + '/app/views');
app.set('view engine', 'ejs');
app.use(session({ secret: 'ilovebunnyrabbits' }));
app.use(passport.initialize());
app.use(passport.session());

app.get('/',
  function(req, res) {
    res.render('index', { user: req.user, search: "", book: "", owned: "" });

  });

  app.get('/login',
  function(req, res){
    res.render('login');
  });

  app.get('/mybooks',
  function(req, res) {
    var books = [];
    //find a user, get their book list.

    //look up each book add to book array
    console.log(req.user);
     Users.findOne({
            		  'id': req.user.id
        		  }, function(err, user) {
            	  	if (err) {
                	  	return err;
            	  	}
        if (user.books.length ==0){
             res.render('mybooks', { user: user, books: "" });
        }
        var z =0;
    		for (var i=0; i<user.books.length; i++){

    		  Books.findOne({
            		  'bookid': req.user.books[i]
        		  }, function(err, book) {
            	  	if (err) {
                	  	return err;
            	  	}
            	  	if (book){
            	  	  books[z] = book;
            	  	  z++;
            	  	}
            	  	console.log("i "+ i + "books.length " + user.books.length + "books" + books.length);
            	  	if (books.length == user.books.length){
            	  	    console.log ("Number of books:" + user.books.length);
            	        res.render('mybooks', { user: user, books: books });
            	  	}
        		});
    		}

        		  });

  });

  app.post('/findBook', upload.array(),
  	function(req,res){
  		console.log(req.body.title);

  		//set to only return 1 best match book

  	    var options = {
    		field: 'title',
    		offset: 0,
 			limit: 1,
    		type: 'books',
    		order: 'relevance',
    		lang: 'en'
		};

    	var thisBook = gBooks.search(req.body.title, options, function(error, results) {
    			if ( ! error ) {
     			console.log(results);
     			//book found in google books api, search our data base to see if it exists or add

     			Books.findOne({
            		'bookid': results[0].id
        		}, function(err, book) {
            		if (err) {
                		return err;
            		}
            		//no book found, create one.
        			 if (!book) {

                		book = new Books({
                			bookid:results[0].id,
                	 		title: results[0].title,
                	 	    author: results[0].authors,
                    		rating: results[0].averageRating,
                    		thumbnail: results[0].thumbnail,

                		});
                	book.save(function(err) {
                    	if (err) console.log(err);
                    	console.log(book);

                    	res.render('index', { user: req.user, search: req.body.title, book: book, owned: "" });
                    	return book;

                	});

            	} else {
                	//found book. Return. The only time to check if owned is if we know it's in collection.

                	console.log("found book");
                	console.log(book);
                	var owned = false;
                	if (req.user){
                		console.log(req.user);
                		owned = checkOwnership(book.bookid, req.user, res, req, book, owned);
                	} else {
                		console.log ("the owned status is "+ owned);
                		res.render('index', { user: req.user, search: req.body.title, book: book, owned: owned });
          				return book;
                	}
            }
        });

    		} else {
        		console.log(error);
        		//what to do if error in searching for book
        		res.render('index', { user: req.user, search: req.body.title, book: "", owned: "" });
    		}
		});

  })

  app.post('/addBook', upload.array(),
  	 function(req,res){
  	 	var user = req.user;
  	 	var thisBookID = req.body.bookID;
  			   	Books.findOneAndUpdate(
    					{bookid: req.body.bookID},
    					{$push: {owners: user.id}},
    					{safe: true, upsert: true},
    					function(err, model) {
        					if (err) console.log(err);
			                	Users.findOneAndUpdate(
			    					{id: user.id},
			    					{$push: {books: thisBookID}},
			    					{safe: true, upsert: true},
			    					function(err, model2) {
			    						console.log ("user update:" + model2)
			    						console.log(user);
			        					if (err) console.log(err);
			        					res.render('index', { user: user, search: req.body.title, book: "", owned: true });

			    					}
			    				);

			    					}
			    	);

        		});

passport.serializeUser(function(user, cb) {
  cb(null, user);
});

passport.deserializeUser(function(obj, cb) {
  cb(null, obj);
});

app.get('/auth/facebook',
  passport.authenticate('facebook'));

app.get('/auth/facebook/callback',
  passport.authenticate('facebook', { failureRedirect: '/login' }),
  function(req, res) {
    // Successful authentication, redirect home.
    res.redirect('/');
  });

var port = process.env.PORT || 8080;
app.listen(port,  function () {
	console.log('Node.js listening on port ' + port + '...');
});

//function to check if the user owns a given book
function checkOwnership(bookID, user, res, req, book, owned){
	console.log(bookID + " is the bookID");
	console.log(user.books.indexOf(bookID) + " is the index of bookID");
	if(user.books.indexOf(bookID) >= 0){

		owned = true;
		console.log ("the owned status is "+ owned);
        res.render('index', { user: req.user, search: req.body.title, book: book, owned: owned });

	} else {
		 res.render('index', { user: req.user, search: req.body.title, book: book, owned: owned });

	}

}<|endoftext|>


<commit_before>/*

grained

*/
(function (window, doc) {

    "use strict";

    function grained(ele, opt) {

        var element = null,
            elementId = null,
            selectorElement = null;

        if (typeof ele === 'string') {
            element = doc.getElementById(ele.split('#')[1]);
        }

        if (!element) {
            console.error('Grained: cannot find the element with id ' + ele);
            return;
        } else {
            elementId = element.id;
        }

        //set style for parent
        element.style.position = 'relative';
        element.style.overflow = 'hidden';

        var prefixes = ["", "-moz-", "-o-animation-", "-webkit-","-ms-"];

        //default option values
        var options = {
            animate: true,
            patternWidth: 100,
            patternHeight: 100,
            grainOpacity: 0.1,
            grainDensity: 1,
            grainWidth: 1,
            grainHeight: 1,
            grainChaos: 5,
            grainSpeed: 10

        };

        Object.keys(opt).forEach(function (key) {
            options[key] = opt[key];
        });

        //selecter element to add grains
        selectorElement = '#' + elementId + '::after';

        var generateNoise = function () {
            var canvas = doc.createElement('canvas');
            var ctx = canvas.getContext('2d');
            canvas.width = options.patternWidth;
            canvas.height = options.patternHeight;
            for (var w = 0; w < options.patternWidth; w += options.grainDensity) {
                for (var h = 0; h < options.patternHeight; h += options.grainDensity) {
                    var rgb = Math.random() * 256 | 0;
                    ctx.fillStyle = 'rgba(' + [rgb, rgb, rgb, options.grainOpacity].join() + ')';
                    ctx.fillRect(w, h, options.grainWidth, options.grainHeight);
                }
            }
            return canvas.toDataURL('image/png');
        };

        function addCSSRule(sheet, selector, rules, index) {
            var ins = '';
            if (selector.length) {
                ins = selector + "{" + rules + "}";
            } else {
                ins = rules;
            }

            if ("insertRule" in sheet) {
                sheet.insertRule(ins, index);
            } else if ("addRule" in sheet) {
                sheet.addRule(selector, rules, index);
            }
        }

        var noise = generateNoise();

        var animation = '',
            keyFrames = ['0%:0%,0%','10%:-10%,10%','20%:10%,-10%','30%:-30%,30%','40%::-20%,20%','50%:15%,0%','60%:20%,-20%','70%:-5%,20%','80%:10%,-10%','90%:-30%,10%','100%:0%,0%'];

        var pre = prefixes.length;
        while (pre--) {
            animation += '@' + prefixes[pre] + 'keyframes grained{';
            for(var key = 0;key < keyFrames.length;key++) {
                var keyVal = keyFrames[key].split(':');
                animation += keyVal[0]+'{';
                animation += prefixes[pre] +'transform:translate('+keyVal[1]+');';
                animation += '}';
            }
            animation += '}';
        }

        console.log(animation);
        var styleAdded = doc.getElementById('grained-animation');
        if (styleAdded) {
            styleAdded.parentElement.removeChild(styleAdded);
        }

        var style = doc.createElement("style");
        style.type = "text/css";
        style.id = 'grained-animation';
        if (options.animate) {
            style.innerHTML = animation;
        } else {
            style.innerHTML = '';
        }
        doc.body.appendChild(style);

        var rule = 'background-image: url(' + noise + ');';
        rule += 'display: block;position: absolute;content: "";height: 300%;width: 300%;left: -100%;top: -100%;z-index: 1;';
        pre = prefixes.length;
        while (pre--) {
            rule += prefixes[pre] + 'animation-name:grained;';
            rule += prefixes[pre] + 'animation-iteration-count: infinite;';
            rule += prefixes[pre] + 'animation-duration: ' + Math.round(options.grainChaos) + 's;';
            rule += prefixes[pre] + 'animation-timing-function: steps(' + Math.round(options.grainSpeed) + ', end);';
        }

        addCSSRule(style.sheet, selectorElement, rule);

    }

    window.grained = grained;
    //END
})(window, document);<commit_msg>Animation fix<commit_after>/*

grained

*/
(function (window, doc) {

    "use strict";

    function grained(ele, opt) {

        var element = null,
            elementId = null,
            selectorElement = null;

        if (typeof ele === 'string') {
            element = doc.getElementById(ele.split('#')[1]);
        }

        if (!element) {
            console.error('Grained: cannot find the element with id ' + ele);
            return;
        } else {
            elementId = element.id;
        }

        //set style for parent
        if (element.style.position !== 'absolute') {
            element.style.position = 'relative';
        }
        element.style.overflow = 'hidden';

        var prefixes = ["", "-moz-", "-o-animation-", "-webkit-", "-ms-"];

        //default option values
        var options = {
            animate: true,
            patternWidth: 100,
            patternHeight: 100,
            grainOpacity: 0.1,
            grainDensity: 1,
            grainWidth: 1,
            grainHeight: 1,
            grainChaos: 0.5,
            grainSpeed: 20

        };

        Object.keys(opt).forEach(function (key) {
            options[key] = opt[key];
        });

        var generateNoise = function () {
            var canvas = doc.createElement('canvas');
            var ctx = canvas.getContext('2d');
            canvas.width = options.patternWidth;
            canvas.height = options.patternHeight;
            for (var w = 0; w < options.patternWidth; w += options.grainDensity) {
                for (var h = 0; h < options.patternHeight; h += options.grainDensity) {
                    var rgb = Math.random() * 256 | 0;
                    ctx.fillStyle = 'rgba(' + [rgb, rgb, rgb, options.grainOpacity].join() + ')';
                    ctx.fillRect(w, h, options.grainWidth, options.grainHeight);
                }
            }
            return canvas.toDataURL('image/png');
        };

        function addCSSRule(sheet, selector, rules, index) {
            var ins = '';
            if (selector.length) {
                ins = selector + "{" + rules + "}";
            } else {
                ins = rules;
            }

            if ("insertRule" in sheet) {
                sheet.insertRule(ins, index);
            } else if ("addRule" in sheet) {
                sheet.addRule(selector, rules, index);
            }
        }

        var noise = generateNoise();

        var animation = '',
            keyFrames = ['0%:-10%,10%', '10%:-25%,0%', '20%:-30%,10%', '30%:-30%,30%', '40%::-20%,20%', '50%:-15%,10%', '60%:-20%,20%', '70%:-5%,20%', '80%:-25%,5%', '90%:-30%,25%', '100%:-10%,10%'];

        var pre = prefixes.length;
        while (pre--) {
            animation += '@' + prefixes[pre] + 'keyframes grained{';
            for (var key = 0; key < keyFrames.length; key++) {
                var keyVal = keyFrames[key].split(':');
                animation += keyVal[0] + '{';
                animation += prefixes[pre] + 'transform:translate(' + keyVal[1] + ');';
                animation += '}';
            }
            animation += '}';
        }

        var styleAdded = doc.getElementById('grained-animation-' + elementId);
        if (styleAdded) {
            styleAdded.parentElement.removeChild(styleAdded);
        }

        var style = doc.createElement("style");
        style.type = "text/css";
        style.id = 'grained-animation-' + elementId;
        if (options.animate) {
            style.innerHTML = animation;
        } else {
            style.innerHTML = '';
        }
        doc.body.appendChild(style);

        var rule = 'background-image: url(' + noise + ');';
        rule += 'position: absolute;content: "";height: 300%;width: 300%;left: -100%;top: -100%;';
        pre = prefixes.length;
        if (options.animate) {
            while (pre--) {
                rule += prefixes[pre] + 'animation-name:grained;';
                rule += prefixes[pre] + 'animation-iteration-count: infinite;';
                rule += prefixes[pre] + 'animation-duration: ' + options.grainChaos + 's;';
                rule += prefixes[pre] + 'animation-timing-function: steps(' +options.grainSpeed + ', end);';
            }
        }

        var graine = document.createElement('div');
        graine.setAttribute('class', 'grained');
        // element.parentElement.removeChild()
        // element.insertBefore(graine, element.firstChild);

        //selecter element to add grains
        selectorElement = '#' + elementId + '::before';

        addCSSRule(style.sheet, selectorElement, rule);

    }

    window.grained = grained;
    //END
})(window, document);<|endoftext|>