<commit_before>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Ajax.org Code Editor (ACE).
 *
 * The Initial Developer of the Original Code is
 * Ajax.org B.V.
 * Portions created by the Initial Developer are Copyright (C) 2010
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *      Fabian Jakobs <fabian AT ajax DOT org>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {

var oop = require("pilot/oop");
var EventEmitter = require("pilot/event_emitter").EventEmitter;

var WorkerClient = function(topLevelNamespaces, packagedJs, module, classname) {

    this.callbacks = [];

    if (require.packaged) {
        var base = this.$guessBasePath();
        var worker = this.$worker = new Worker(base + packagedJs);
    }
    else {
        var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
        var worker = this.$worker = new Worker(workerUrl);

        var tlns = {};
        for (var i=0; i<topLevelNamespaces.length; i++) {
            var ns = topLevelNamespaces[i];
            var path = this.$normalizePath(require.nameToUrl(ns, null, "_").replace(/.js$/, ""));

            tlns[ns] = path;
        }
    }

    this.$worker.postMessage({
        init : true,
        tlns: tlns,
        module: module,
        classname: classname
    });

    this.callbackId = 1;
    this.callbacks = {};

    var _self = this;
    this.$worker.onerror = function(e) {
        window.console && console.log && console.log(e);
        throw e;
    };
    this.$worker.onmessage = function(e) {
        var msg = e.data;
        switch(msg.type) {
            case "log":
                window.console && console.log && console.log(msg.data);
                break;

            case "event":
                _self._dispatchEvent(msg.name, {data: msg.data});
                break;

            case "call":
                var callback = _self.callbacks[msg.id];
                if (callback) {
                    callback(msg.data);
                    delete _self.callbacks[msg.id];
                }
                break;
        }
    };
};

(function(){

    oop.implement(this, EventEmitter);

    this.$normalizePath = function(path) {
        if (!path.match(/^\w+:/))
            path = location.protocol + "//" + location.host + location.pathname.replace(/\/.*?$/, "/") + "/" + path.replace(/^\//, "");
        return path;
    };

    this.$guessBasePath = function() {
        if (require.aceBaseUrl)
            return require.aceBaseUrl;

        var scripts = document.getElementsByTagName("script");
        for (var i=0; i<scripts.length; i++) {
            var script = scripts[i];

            var base = script.getAttribute("data-ace-base");
            if (base)
                return base.replace(/\/*$/, "/");

            var src = script.src || script.getAttribute("src");
            if (!src) {
                continue;
            }
            var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace-uncompressed\.js)(?:\?|$)/);
            if (m)
                return m[1] || m[2];
        }
        return "";
    };

    this.terminate = function() {
        this._dispatchEvent("terminate", {});
        this.$worker.terminate();
    };

    this.send = function(cmd, args) {
        this.$worker.postMessage({command: cmd, args: args});
    };

    this.call = function(cmd, args, callback) {
        if (callback) {
            var id = this.callbackId++;
            this.callbacks[id] = callback;
            args.push(id);
        }
        this.send(cmd, args);
    };

    this.emit = function(event, data) {
        this.$worker.postMessage({event: event, data: data});
    };

}).call(WorkerClient.prototype);

exports.WorkerClient = WorkerClient;

});
<commit_msg>another worker loader tweak<commit_after>/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (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.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Ajax.org Code Editor (ACE).
 *
 * The Initial Developer of the Original Code is
 * Ajax.org B.V.
 * Portions created by the Initial Developer are Copyright (C) 2010
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *      Fabian Jakobs <fabian AT ajax DOT org>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */

define(function(require, exports, module) {

var oop = require("pilot/oop");
var EventEmitter = require("pilot/event_emitter").EventEmitter;

var WorkerClient = function(topLevelNamespaces, packagedJs, module, classname) {

    this.callbacks = [];

    if (require.packaged) {
        var base = this.$guessBasePath();
        var worker = this.$worker = new Worker(base + packagedJs);
    }
    else {
        var workerUrl = this.$normalizePath(require.nameToUrl("ace/worker/worker", null, "_"));
        var worker = this.$worker = new Worker(workerUrl);

        var tlns = {};
        for (var i=0; i<topLevelNamespaces.length; i++) {
            var ns = topLevelNamespaces[i];
            var path = this.$normalizePath(require.nameToUrl(ns, null, "_").replace(/.js$/, ""));

            tlns[ns] = path;
        }
    }

    this.$worker.postMessage({
        init : true,
        tlns: tlns,
        module: module,
        classname: classname
    });

    this.callbackId = 1;
    this.callbacks = {};

    var _self = this;
    this.$worker.onerror = function(e) {
        window.console && console.log && console.log(e);
        throw e;
    };
    this.$worker.onmessage = function(e) {
        var msg = e.data;
        switch(msg.type) {
            case "log":
                window.console && console.log && console.log(msg.data);
                break;

            case "event":
                _self._dispatchEvent(msg.name, {data: msg.data});
                break;

            case "call":
                var callback = _self.callbacks[msg.id];
                if (callback) {
                    callback(msg.data);
                    delete _self.callbacks[msg.id];
                }
                break;
        }
    };
};

(function(){

    oop.implement(this, EventEmitter);

    this.$normalizePath = function(path) {
        if (!path.match(/^\w+:/))
            path = location.protocol + "//" + location.host + location.pathname.replace(/\/.*?$/, "") + "/" + path.replace(/^\//, "");
        return path;
    };

    this.$guessBasePath = function() {
        if (require.aceBaseUrl)
            return require.aceBaseUrl;

        var scripts = document.getElementsByTagName("script");
        for (var i=0; i<scripts.length; i++) {
            var script = scripts[i];

            var base = script.getAttribute("data-ace-base");
            if (base)
                return base.replace(/\/*$/, "/");

            var src = script.src || script.getAttribute("src");
            if (!src) {
                continue;
            }
            var m = src.match(/^(?:(.*\/)ace\.js|(.*\/)ace-uncompressed\.js)(?:\?|$)/);
            if (m)
                return m[1] || m[2];
        }
        return "";
    };

    this.terminate = function() {
        this._dispatchEvent("terminate", {});
        this.$worker.terminate();
    };

    this.send = function(cmd, args) {
        this.$worker.postMessage({command: cmd, args: args});
    };

    this.call = function(cmd, args, callback) {
        if (callback) {
            var id = this.callbackId++;
            this.callbacks[id] = callback;
            args.push(id);
        }
        this.send(cmd, args);
    };

    this.emit = function(event, data) {
        this.$worker.postMessage({event: event, data: data});
    };

}).call(WorkerClient.prototype);

exports.WorkerClient = WorkerClient;

});
<|endoftext|>


<commit_before>/* https://github.com/DiemenDesign/summernote-cleaner */
(function (factory) {
  if (typeof define === 'function' && define.amd) {
    define(['jquery'], factory);
  } else if (typeof module === 'object' && module.exports) {
    module.exports = factory(require('jquery'));
  } else {
    factory(window.jQuery);
  }
}
(function ($) {
  $.extend(true, $.summernote.lang, {
    'en-US': {
      cleaner: {
        tooltip: 'Cleaner',
        not: 'Text has been Cleaned!!!',
        limitText: 'Text',
        limitHTML: 'HTML'
      }
    }
  });
  $.extend($.summernote.options, {
    cleaner: {
      action: 'both', // both|button|paste 'button' only cleans via toolbar button, 'paste' only clean when pasting content, both does both options.
      newline: '
', // Summernote's default is to use '

'
      notStyle: 'position:absolute;top:0;left:0;right:0',
      icon: '<svg xmlns="http://www.w3.org/2000/svg" id="libre-paintbrush" viewBox="0 0 14 14" width="14" height="14"><path d="m 11.821425,1 q 0.46875,0 0.82031,0.311384 0.35157,0.311384 0.35157,0.780134 0,0.421875 -0.30134,1.01116 -2.22322,4.212054 -3.11384,5.035715 -0.64956,0.609375 -1.45982,0.609375 -0.84375,0 -1.44978,-0.61942 -0.60603,-0.61942 -0.60603,-1.469866 0,-0.857143 0.61608,-1.419643 l 4.27232,-3.877232 Q 11.345985,1 11.821425,1 z m -6.08705,6.924107 q 0.26116,0.508928 0.71317,0.870536 0.45201,0.361607 1.00781,0.508928 l 0.007,0.475447 q 0.0268,1.426339 -0.86719,2.32366 Q 5.700895,13 4.261155,13 q -0.82366,0 -1.45982,-0.311384 -0.63616,-0.311384 -1.0212,-0.853795 -0.38505,-0.54241 -0.57924,-1.225446 -0.1942,-0.683036 -0.1942,-1.473214 0.0469,0.03348 0.27455,0.200893 0.22768,0.16741 0.41518,0.29799 0.1875,0.130581 0.39509,0.24442 0.20759,0.113839 0.30804,0.113839 0.27455,0 0.3683,-0.247767 0.16741,-0.441965 0.38505,-0.753349 0.21763,-0.311383 0.4654,-0.508928 0.24776,-0.197545 0.58928,-0.31808 0.34152,-0.120536 0.68974,-0.170759 0.34821,-0.05022 0.83705,-0.07031 z"/></svg>',
      keepHtml: true, //Remove all Html formats
      keepOnlyTags: [], // If keepHtml is true, remove all tags except these
      keepClasses: false, //Remove Classes
      badTags: ['style', 'script', 'applet', 'embed', 'noframes', 'noscript', 'html'], //Remove full tags with contents
      badAttributes: ['style', 'start'], //Remove attributes from remaining tags
      limitChars: 520, // 0|# 0 disables option
      limitDisplay: 'both', // none|text|html|both
      limitStop: false // true/false
    }
  });
  $.extend($.summernote.plugins, {
    'cleaner':function (context) {
      var self = this,
            ui = $.summernote.ui,
         $note = context.layoutInfo.note,
       $editor = context.layoutInfo.editor,
       options = context.options,
          lang = options.langInfo;
      var cleanText = function (txt, nlO) {
        var out = txt;
        if (!options.cleaner.keepClasses) {
          var sS = /(\n|\r| class=(")?Mso[a-zA-Z]+(")?)/g;
             out = txt.replace(sS, ' ');
        }
        var nL = /(\n)+/g;
           out = out.replace(nL, nlO);
        if (options.cleaner.keepHtml) {
          var cS = new RegExp('', 'gi');
             out = out.replace(cS, '');
          var tS = new RegExp('<(/)*(meta|link|\\?xml:|st1:|o:|font)(.*?)>', 'gi');
             out = out.replace(tS, '');
          var bT = options.cleaner.badTags;
          for (var i = 0; i < bT.length; i++) {
            tS = new RegExp('<' + bT[i] + '\\b.*>.*</' + bT[i] + '>', 'gi');
            out = out.replace(tS, '');
          }
          var allowedTags = options.cleaner.keepOnlyTags;
          if (typeof(allowedTags) == "undefined") allowedTags = [];
          if (allowedTags.length > 0) {
            allowedTags = (((allowedTags||'') + '').toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join('');
               var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi;
                    out = out.replace(tags, function($0, $1) {
              return allowedTags.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : ''
            });
          }
          var bA = options.cleaner.badAttributes;
          for (var ii = 0; ii < bA.length; ii++ ) {
            //var aS=new RegExp(' ('+bA[ii]+'="(.*?)")|('+bA[ii]+'=\'(.*?)\')', 'gi');
            var aS = new RegExp(' ' + bA[ii] + '=[\'|"](.*?)[\'|"]', 'gi');
               out = out.replace(aS, '');
          }
        }
        return out;
      };
      if (options.cleaner.action == 'both' || options.cleaner.action == 'button') {
        context.memo('button.cleaner', function () {
          var button = ui.button({
            contents: options.cleaner.icon,
            tooltip: lang.cleaner.tooltip,
            container: 'body',
            click:function () {
              if ($note.summernote('createRange').toString())
                $note.summernote('pasteHTML', $note.summernote('createRange').toString());
              else
                $note.summernote('code', cleanText($note.summernote('code')));
              if ($editor.find('.note-status-output').length > 0)
                $editor.find('.note-status-output').html('
' + lang.cleaner.not + '
');
              else
                $editor.find('.note-editing-area').append('
' + lang.cleaner.not + '
');
            }
          });
          return button.render();
        });
      }
      this.events = {
        'summernote.init':function () {
          if ($editor.find('.note-status-output').length < 1) {
            $editor.find('.note-statusbar').prepend('<output class="note-status-output"></output>');
            $("head").append('');
          }
          if (options.cleaner.limitChars != 0 || options.cleaner.limitDisplay != 'none') {
              var textLength = $editor.find(".note-editable").text().replace(/(<([^>]+)>)/ig, "").replace(/( )/, " ");
              var codeLength = $editor.find('.note-editable').html();
            var lengthStatus = '';
            if (textLength.length > options.cleaner.limitChars && options.cleaner.limitChars > 0)
              lengthStatus += 'text-danger">';
            else
              lengthStatus += '">';
            if (options.cleaner.limitDisplay == 'text' || options.cleaner.limitDisplay == 'both') lengthStatus += lang.cleaner.limitText + ': ' + textLength.length;
            if (options.cleaner.limitDisplay == 'both') lengthStatus += ' / ';
            if (options.cleaner.limitDisplay == 'html' || options.cleaner.limitDisplay == 'both') lengthStatus += lang.cleaner.limitHTML + ': ' + codeLength.length;
            $editor.find('.note-status-output').html('<small class="pull-right ' + lengthStatus + ' ');
          }
        },
        'summernote.keydown':function (we, e) {
          if (options.cleaner.limitChars != 0 || options.cleaner.limitDisplay != 'none') {
              var textLength =  $editor.find(".note-editable").text().replace(/(<([^>]+)>)/ig, "").replace(/( )/, " ");
              var codeLength =  $editor.find('.note-editable').html();
            var lengthStatus = '';
            if (options.cleaner.limitStop == true && textLength.length >= options.cleaner.limitChars) {
                   var key = e.keyCode;
              allowed_keys = [8, 37, 38, 39, 40, 46]
              if ($.inArray(key, allowed_keys) != -1) {
                $editor.find('.cleanerLimit').removeClass('text-danger');
                return true;
              } else {
                $editor.find('.cleanerLimit').addClass('text-danger');
                e.preventDefault();
                e.stopPropagation();
              }
            } else {
              if (textLength.length > options.cleaner.limitChars && options.cleaner.limitChars > 0)
                lengthStatus += 'text-danger">';
              else
                lengthStatus += '">';
              if (options.cleaner.limitDisplay == 'text' || options.cleaner.limitDisplay == 'both')
                lengthStatus += lang.cleaner.limitText + ': ' + textLength.length;
              if (options.cleaner.limitDisplay == 'both')
                lengthStatus += ' / ';
              if (options.cleaner.limitDisplay == 'html' || options.cleaner.limitDisplay == 'both')
                lengthStatus += lang.cleaner.limitHTML + ': ' + codeLength.length;
              $editor.find('.note-status-output').html('<small class="cleanerLimit pull-right ' + lengthStatus + ' ');
            }
          }
        },
        'summernote.paste':function (we, e) {
          if (options.cleaner.action == 'both' || options.cleaner.action == 'paste') {
            e.preventDefault();
              var ua = window.navigator.userAgent;
            var msie = ua.indexOf("MSIE ");
                msie = msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./);
            var ffox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
            if (msie)
              var text = window.clipboardData.getData("Text");
            else
              var text = e.originalEvent.clipboardData.getData(options.cleaner.keepHtml ? 'Text' : 'text/plain');
            if (text) {
              if (msie || ffox)
                setTimeout(function(){$note.summernote('pasteHTML', cleanText(text, options.cleaner.newline));}, 1);
              else
                $note.summernote('pasteHTML', cleanText(text, options.cleaner.newline));
              if ($editor.find('.note-status-output').length > 0)
                $editor.find('.note-status-output').html('
' + lang.cleaner.not + '
');
              else
                $editor.find('.note-resizebar').append('
' + lang.cleaner.not + '
');
            }
          }
        }
      }
    }
  });
}));
<commit_msg>Fix keepHtml flag<commit_after>/* https://github.com/DiemenDesign/summernote-cleaner */
(function (factory) {
  if (typeof define === 'function' && define.amd) {
    define(['jquery'], factory);
  } else if (typeof module === 'object' && module.exports) {
    module.exports = factory(require('jquery'));
  } else {
    factory(window.jQuery);
  }
}
(function ($) {
  $.extend(true, $.summernote.lang, {
    'en-US': {
      cleaner: {
        tooltip: 'Cleaner',
        not: 'Text has been Cleaned!!!',
        limitText: 'Text',
        limitHTML: 'HTML'
      }
    }
  });
  $.extend($.summernote.options, {
    cleaner: {
      action: 'both', // both|button|paste 'button' only cleans via toolbar button, 'paste' only clean when pasting content, both does both options.
      newline: '
', // Summernote's default is to use '

'
      notStyle: 'position:absolute;top:0;left:0;right:0',
      icon: '<svg xmlns="http://www.w3.org/2000/svg" id="libre-paintbrush" viewBox="0 0 14 14" width="14" height="14"><path d="m 11.821425,1 q 0.46875,0 0.82031,0.311384 0.35157,0.311384 0.35157,0.780134 0,0.421875 -0.30134,1.01116 -2.22322,4.212054 -3.11384,5.035715 -0.64956,0.609375 -1.45982,0.609375 -0.84375,0 -1.44978,-0.61942 -0.60603,-0.61942 -0.60603,-1.469866 0,-0.857143 0.61608,-1.419643 l 4.27232,-3.877232 Q 11.345985,1 11.821425,1 z m -6.08705,6.924107 q 0.26116,0.508928 0.71317,0.870536 0.45201,0.361607 1.00781,0.508928 l 0.007,0.475447 q 0.0268,1.426339 -0.86719,2.32366 Q 5.700895,13 4.261155,13 q -0.82366,0 -1.45982,-0.311384 -0.63616,-0.311384 -1.0212,-0.853795 -0.38505,-0.54241 -0.57924,-1.225446 -0.1942,-0.683036 -0.1942,-1.473214 0.0469,0.03348 0.27455,0.200893 0.22768,0.16741 0.41518,0.29799 0.1875,0.130581 0.39509,0.24442 0.20759,0.113839 0.30804,0.113839 0.27455,0 0.3683,-0.247767 0.16741,-0.441965 0.38505,-0.753349 0.21763,-0.311383 0.4654,-0.508928 0.24776,-0.197545 0.58928,-0.31808 0.34152,-0.120536 0.68974,-0.170759 0.34821,-0.05022 0.83705,-0.07031 z"/></svg>',
      keepHtml: true, //Remove all Html formats
      keepOnlyTags: [], // If keepHtml is true, remove all tags except these
      keepClasses: false, //Remove Classes
      badTags: ['style', 'script', 'applet', 'embed', 'noframes', 'noscript', 'html'], //Remove full tags with contents
      badAttributes: ['style', 'start'], //Remove attributes from remaining tags
      limitChars: 520, // 0|# 0 disables option
      limitDisplay: 'both', // none|text|html|both
      limitStop: false // true/false
    }
  });
  $.extend($.summernote.plugins, {
    'cleaner':function (context) {
      var self = this,
            ui = $.summernote.ui,
         $note = context.layoutInfo.note,
       $editor = context.layoutInfo.editor,
       options = context.options,
          lang = options.langInfo;
      var cleanText = function (txt, nlO) {
        var out = txt;
        if (!options.cleaner.keepClasses) {
          var sS = /(\n|\r| class=(")?Mso[a-zA-Z]+(")?)/g;
             out = txt.replace(sS, ' ');
        }
        var nL = /(\n)+/g;
           out = out.replace(nL, nlO);
        if (options.cleaner.keepHtml) {
          var cS = new RegExp('', 'gi');
             out = out.replace(cS, '');
          var tS = new RegExp('<(/)*(meta|link|\\?xml:|st1:|o:|font)(.*?)>', 'gi');
             out = out.replace(tS, '');
          var bT = options.cleaner.badTags;
          for (var i = 0; i < bT.length; i++) {
            tS = new RegExp('<' + bT[i] + '\\b.*>.*</' + bT[i] + '>', 'gi');
            out = out.replace(tS, '');
          }
          var allowedTags = options.cleaner.keepOnlyTags;
          if (typeof(allowedTags) == "undefined") allowedTags = [];
          if (allowedTags.length > 0) {
            allowedTags = (((allowedTags||'') + '').toLowerCase().match(/<[a-z][a-z0-9]*>/g) || []).join('');
               var tags = /<\/?([a-z][a-z0-9]*)\b[^>]*>/gi;
                    out = out.replace(tags, function($0, $1) {
              return allowedTags.indexOf('<' + $1.toLowerCase() + '>') > -1 ? $0 : ''
            });
          }
          var bA = options.cleaner.badAttributes;
          for (var ii = 0; ii < bA.length; ii++ ) {
            //var aS=new RegExp(' ('+bA[ii]+'="(.*?)")|('+bA[ii]+'=\'(.*?)\')', 'gi');
            var aS = new RegExp(' ' + bA[ii] + '=[\'|"](.*?)[\'|"]', 'gi');
               out = out.replace(aS, '');

               aS = new RegExp(" " + bA[ii] + "=(.*?) ", "gi");
               out = out.replace(aS, " ");
               aS = new RegExp(" " + bA[ii] + "=(.*?)>", "gi");
               out = out.replace(aS, ">");
          }
        }

        var sS = new RegExp("[ ]{1,}>", "gi");
        out = out.replace(sS, ">");
        return out;
      };
      if (options.cleaner.action == 'both' || options.cleaner.action == 'button') {
        context.memo('button.cleaner', function () {
          var button = ui.button({
            contents: options.cleaner.icon,
            tooltip: lang.cleaner.tooltip,
            container: 'body',
            click:function () {
              if ($note.summernote('createRange').toString())
                $note.summernote('pasteHTML', $note.summernote('createRange').toString());
              else
                $note.summernote('code', cleanText($note.summernote('code')));
              if ($editor.find('.note-status-output').length > 0)
                $editor.find('.note-status-output').html('
' + lang.cleaner.not + '
');
              else
                $editor.find('.note-editing-area').append('
' + lang.cleaner.not + '
');
            }
          });
          return button.render();
        });
      }
      this.events = {
        'summernote.init':function () {
          if ($editor.find('.note-status-output').length < 1) {
            $editor.find('.note-statusbar').prepend('<output class="note-status-output"></output>');
            $("head").append('');
          }
          if (options.cleaner.limitChars != 0 || options.cleaner.limitDisplay != 'none') {
              var textLength = $editor.find(".note-editable").text().replace(/(<([^>]+)>)/ig, "").replace(/( )/, " ");
              var codeLength = $editor.find('.note-editable').html();
            var lengthStatus = '';
            if (textLength.length > options.cleaner.limitChars && options.cleaner.limitChars > 0)
              lengthStatus += 'text-danger">';
            else
              lengthStatus += '">';
            if (options.cleaner.limitDisplay == 'text' || options.cleaner.limitDisplay == 'both') lengthStatus += lang.cleaner.limitText + ': ' + textLength.length;
            if (options.cleaner.limitDisplay == 'both') lengthStatus += ' / ';
            if (options.cleaner.limitDisplay == 'html' || options.cleaner.limitDisplay == 'both') lengthStatus += lang.cleaner.limitHTML + ': ' + codeLength.length;
            $editor.find('.note-status-output').html('<small class="pull-right ' + lengthStatus + ' ');
          }
        },
        'summernote.keydown':function (we, e) {
          if (options.cleaner.limitChars != 0 || options.cleaner.limitDisplay != 'none') {
              var textLength =  $editor.find(".note-editable").text().replace(/(<([^>]+)>)/ig, "").replace(/( )/, " ");
              var codeLength =  $editor.find('.note-editable').html();
            var lengthStatus = '';
            if (options.cleaner.limitStop == true && textLength.length >= options.cleaner.limitChars) {
                   var key = e.keyCode;
              allowed_keys = [8, 37, 38, 39, 40, 46]
              if ($.inArray(key, allowed_keys) != -1) {
                $editor.find('.cleanerLimit').removeClass('text-danger');
                return true;
              } else {
                $editor.find('.cleanerLimit').addClass('text-danger');
                e.preventDefault();
                e.stopPropagation();
              }
            } else {
              if (textLength.length > options.cleaner.limitChars && options.cleaner.limitChars > 0)
                lengthStatus += 'text-danger">';
              else
                lengthStatus += '">';
              if (options.cleaner.limitDisplay == 'text' || options.cleaner.limitDisplay == 'both')
                lengthStatus += lang.cleaner.limitText + ': ' + textLength.length;
              if (options.cleaner.limitDisplay == 'both')
                lengthStatus += ' / ';
              if (options.cleaner.limitDisplay == 'html' || options.cleaner.limitDisplay == 'both')
                lengthStatus += lang.cleaner.limitHTML + ': ' + codeLength.length;
              $editor.find('.note-status-output').html('<small class="cleanerLimit pull-right ' + lengthStatus + ' ');
            }
          }
        },
        'summernote.paste':function (we, e) {
          if (options.cleaner.action == 'both' || options.cleaner.action == 'paste') {
            e.preventDefault();
              var ua = window.navigator.userAgent;
            var msie = ua.indexOf("MSIE ");
                msie = msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./);
            var ffox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
            if (msie)
              var text = window.clipboardData.getData("text/html");
            else
              var text = e.originalEvent.clipboardData.getData(options.cleaner.keepHtml ? 'text/html' : 'text/plain');
            if (text) {
              if (msie || ffox)
                setTimeout(function(){$note.summernote('pasteHTML', cleanText(text, options.cleaner.newline));}, 1);
              else
                $note.summernote('pasteHTML', cleanText(text, options.cleaner.newline));
              if ($editor.find('.note-status-output').length > 0)
                $editor.find('.note-status-output').html('
' + lang.cleaner.not + '
');
              else
                $editor.find('.note-resizebar').append('
' + lang.cleaner.not + '
');
            }
          }
        }
      }
    }
  });
}));
<|endoftext|>


<commit_before>(function(self) {
  'use strict';

  if (self.fetch) {
    return
  }

  var support = {
    searchParams: 'URLSearchParams' in self,
    iterable: 'Symbol' in self && 'iterator' in Symbol,
    blob: 'FileReader' in self && 'Blob' in self && (function() {
      try {
        new Blob()
        return true
      } catch(e) {
        return false
      }
    })(),
    formData: 'FormData' in self,
    arrayBuffer: 'ArrayBuffer' in self
  }

  function normalizeName(name) {
    if (typeof name !== 'string') {
      name = String(name)
    }
    if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
      throw new TypeError('Invalid character in header field name')
    }
    return name.toLowerCase()
  }

  function normalizeValue(value) {
    if (typeof value !== 'string') {
      value = String(value)
    }
    return value
  }

  // Build a destructive iterator for the value list
  function iteratorFor(items) {
    var iterator = {
      next: function() {
        var value = items.shift()
        return {done: value === undefined, value: value}
      }
    }

    if (support.iterable) {
      iterator[Symbol.iterator] = function() {
        return iterator
      }
    }

    return iterator
  }

  function Headers(headers) {
    this.map = {}

    if (headers instanceof Headers) {
      headers.forEach(function(value, name) {
        this.append(name, value)
      }, this)

    } else if (headers) {
      Object.getOwnPropertyNames(headers).forEach(function(name) {
        this.append(name, headers[name])
      }, this)
    }
  }

  Headers.prototype.append = function(name, value) {
    name = normalizeName(name)
    value = normalizeValue(value)
    var list = this.map[name]
    if (!list) {
      list = []
      this.map[name] = list
    }
    list.push(value)
  }

  Headers.prototype['delete'] = function(name) {
    delete this.map[normalizeName(name)]
  }

  Headers.prototype.get = function(name) {
    var values = this.map[normalizeName(name)]
    return values ? values[0] : null
  }

  Headers.prototype.getAll = function(name) {
    return this.map[normalizeName(name)] || []
  }

  Headers.prototype.has = function(name) {
    return this.map.hasOwnProperty(normalizeName(name))
  }

  Headers.prototype.set = function(name, value) {
    this.map[normalizeName(name)] = [normalizeValue(value)]
  }

  Headers.prototype.forEach = function(callback, thisArg) {
    Object.getOwnPropertyNames(this.map).forEach(function(name) {
      this.map[name].forEach(function(value) {
        callback.call(thisArg, value, name, this)
      }, this)
    }, this)
  }

  Headers.prototype.keys = function() {
    var items = []
    this.forEach(function(value, name) { items.push(name) })
    return iteratorFor(items)
  }

  Headers.prototype.values = function() {
    var items = []
    this.forEach(function(value) { items.push(value) })
    return iteratorFor(items)
  }

  Headers.prototype.entries = function() {
    var items = []
    this.forEach(function(value, name) { items.push([name, value]) })
    return iteratorFor(items)
  }

  if (support.iterable) {
    Headers.prototype[Symbol.iterator] = Headers.prototype.entries
  }

  function consumed(body) {
    if (body.bodyUsed) {
      return Promise.reject(new TypeError('Already read'))
    }
    body.bodyUsed = true
  }

  function fileReaderReady(reader) {
    return new Promise(function(resolve, reject) {
      reader.onload = function() {
        resolve(reader.result)
      }
      reader.onerror = function() {
        reject(reader.error)
      }
    })
  }

  function readBlobAsArrayBuffer(blob) {
    var reader = new FileReader()
    reader.readAsArrayBuffer(blob)
    return fileReaderReady(reader)
  }

  function readBlobAsText(blob) {
    var reader = new FileReader()
    reader.readAsText(blob)
    return fileReaderReady(reader)
  }

  function Body() {
    this.bodyUsed = false

    this._initBody = function(body) {
      this._bodyInit = body
      if (typeof body === 'string') {
        this._bodyText = body
      } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
        this._bodyBlob = body
      } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
        this._bodyFormData = body
      } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
        this._bodyText = body.toString()
      } else if (!body) {
        this._bodyText = ''
      } else if (support.arrayBuffer && ArrayBuffer.prototype.isPrototypeOf(body)) {
        // Only support ArrayBuffers for POST method.
        // Receiving ArrayBuffers happens via Blobs, instead.
      } else {
        throw new Error('unsupported BodyInit type')
      }

      if (!this.headers.get('content-type')) {
        if (typeof body === 'string') {
          this.headers.set('content-type', 'text/plain;charset=UTF-8')
        } else if (this._bodyBlob && this._bodyBlob.type) {
          this.headers.set('content-type', this._bodyBlob.type)
        } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
          this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')
        }
      }
    }

    if (support.blob) {
      this.blob = function() {
        var rejected = consumed(this)
        if (rejected) {
          return rejected
        }

        if (this._bodyBlob) {
          return Promise.resolve(this._bodyBlob)
        } else if (this._bodyFormData) {
          throw new Error('could not read FormData body as blob')
        } else {
          return Promise.resolve(new Blob([this._bodyText]))
        }
      }

      this.arrayBuffer = function() {
        return this.blob().then(readBlobAsArrayBuffer)
      }

      this.text = function() {
        var rejected = consumed(this)
        if (rejected) {
          return rejected
        }

        if (this._bodyBlob) {
          return readBlobAsText(this._bodyBlob)
        } else if (this._bodyFormData) {
          throw new Error('could not read FormData body as text')
        } else {
          return Promise.resolve(this._bodyText)
        }
      }
    } else {
      this.text = function() {
        var rejected = consumed(this)
        return rejected ? rejected : Promise.resolve(this._bodyText)
      }
    }

    if (support.formData) {
      this.formData = function() {
        return this.text().then(decode)
      }
    }

    this.json = function() {
      return this.text().then(JSON.parse)
    }

    return this
  }

  // HTTP methods whose capitalization should be normalized
  var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']

  function normalizeMethod(method) {
    var upcased = method.toUpperCase()
    return (methods.indexOf(upcased) > -1) ? upcased : method
  }

  function Request(input, options) {
    options = options || {}
    var body = options.body
    if (Request.prototype.isPrototypeOf(input)) {
      if (input.bodyUsed) {
        throw new TypeError('Already read')
      }
      this.url = input.url
      this.credentials = input.credentials
      if (!options.headers) {
        this.headers = new Headers(input.headers)
      }
      this.method = input.method
      this.mode = input.mode
      if (!body) {
        body = input._bodyInit
        input.bodyUsed = true
      }
    } else {
      this.url = input
    }

    this.credentials = options.credentials || this.credentials || 'omit'
    if (options.headers || !this.headers) {
      this.headers = new Headers(options.headers)
    }
    this.method = normalizeMethod(options.method || this.method || 'GET')
    this.mode = options.mode || this.mode || null
    this.referrer = null

    if ((this.method === 'GET' || this.method === 'HEAD') && body) {
      throw new TypeError('Body not allowed for GET or HEAD requests')
    }
    this._initBody(body)
  }

  Request.prototype.clone = function() {
    return new Request(this)
  }

  function decode(body) {
    var form = new FormData()
    body.trim().split('&').forEach(function(bytes) {
      if (bytes) {
        var split = bytes.split('=')
        var name = split.shift().replace(/\+/g, ' ')
        var value = split.join('=').replace(/\+/g, ' ')
        form.append(decodeURIComponent(name), decodeURIComponent(value))
      }
    })
    return form
  }

  function headers(xhr) {
    var head = new Headers()
    var pairs = (xhr.getAllResponseHeaders() || '').trim().split('\n')
    pairs.forEach(function(header) {
      var split = header.trim().split(':')
      var key = split.shift().trim()
      var value = split.join(':').trim()
      head.append(key, value)
    })
    return head
  }

  Body.call(Request.prototype)

  function Response(bodyInit, options) {
    if (!options) {
      options = {}
    }

    this.type = 'default'
    this.status = options.status
    this.ok = this.status >= 200 && this.status < 300
    this.statusText = options.statusText
    this.headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers)
    this.url = options.url || ''
    this._initBody(bodyInit)
  }

  Body.call(Response.prototype)

  Response.prototype.clone = function() {
    return new Response(this._bodyInit, {
      status: this.status,
      statusText: this.statusText,
      headers: new Headers(this.headers),
      url: this.url
    })
  }

  Response.error = function() {
    var response = new Response(null, {status: 0, statusText: ''})
    response.type = 'error'
    return response
  }

  var redirectStatuses = [301, 302, 303, 307, 308]

  Response.redirect = function(url, status) {
    if (redirectStatuses.indexOf(status) === -1) {
      throw new RangeError('Invalid status code')
    }

    return new Response(null, {status: status, headers: {location: url}})
  }

  self.Headers = Headers
  self.Request = Request
  self.Response = Response

  self.fetch = function(input, init) {
    return new Promise(function(resolve, reject) {
      var request
      if (Request.prototype.isPrototypeOf(input) && !init) {
        request = input
      } else {
        request = new Request(input, init)
      }

      var xhr = new XMLHttpRequest()

      function responseURL() {
        if ('responseURL' in xhr) {
          return xhr.responseURL
        }

        // Avoid security warnings on getResponseHeader when not allowed by CORS
        if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) {
          return xhr.getResponseHeader('X-Request-URL')
        }

        return
      }

      xhr.onload = function() {
        var options = {
          status: xhr.status,
          statusText: xhr.statusText,
          headers: headers(xhr),
          url: responseURL()
        }
        var body = 'response' in xhr ? xhr.response : xhr.responseText
        resolve(new Response(body, options))
      }

      xhr.onerror = function() {
        reject(new TypeError('Network request failed'))
      }

      xhr.ontimeout = function() {
        reject(new TypeError('Network request failed'))
      }

      xhr.open(request.method, request.url, true)

      if (request.credentials === 'include') {
        xhr.withCredentials = true
      }

      if ('responseType' in xhr && support.blob) {
        xhr.responseType = 'blob'
      }

      request.headers.forEach(function(value, name) {
        xhr.setRequestHeader(name, value)
      })

      xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
    })
  }
  self.fetch.polyfill = true
})(typeof self !== 'undefined' ? self : this);
<commit_msg>Updated to 2.0.1<commit_after>(function(self) {
  'use strict';

  if (self.fetch) {
    return
  }

  var support = {
    searchParams: 'URLSearchParams' in self,
    iterable: 'Symbol' in self && 'iterator' in Symbol,
    blob: 'FileReader' in self && 'Blob' in self && (function() {
      try {
        new Blob()
        return true
      } catch(e) {
        return false
      }
    })(),
    formData: 'FormData' in self,
    arrayBuffer: 'ArrayBuffer' in self
  }

  if (support.arrayBuffer) {
    var viewClasses = [
      '[object Int8Array]',
      '[object Uint8Array]',
      '[object Uint8ClampedArray]',
      '[object Int16Array]',
      '[object Uint16Array]',
      '[object Int32Array]',
      '[object Uint32Array]',
      '[object Float32Array]',
      '[object Float64Array]'
    ]

    var isDataView = function(obj) {
      return obj && DataView.prototype.isPrototypeOf(obj)
    }

    var isArrayBufferView = ArrayBuffer.isView || function(obj) {
      return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1
    }
  }

  function normalizeName(name) {
    if (typeof name !== 'string') {
      name = String(name)
    }
    if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
      throw new TypeError('Invalid character in header field name')
    }
    return name.toLowerCase()
  }

  function normalizeValue(value) {
    if (typeof value !== 'string') {
      value = String(value)
    }
    return value
  }

  // Build a destructive iterator for the value list
  function iteratorFor(items) {
    var iterator = {
      next: function() {
        var value = items.shift()
        return {done: value === undefined, value: value}
      }
    }

    if (support.iterable) {
      iterator[Symbol.iterator] = function() {
        return iterator
      }
    }

    return iterator
  }

  function Headers(headers) {
    this.map = {}

    if (headers instanceof Headers) {
      headers.forEach(function(value, name) {
        this.append(name, value)
      }, this)

    } else if (headers) {
      Object.getOwnPropertyNames(headers).forEach(function(name) {
        this.append(name, headers[name])
      }, this)
    }
  }

  Headers.prototype.append = function(name, value) {
    name = normalizeName(name)
    value = normalizeValue(value)
    var oldValue = this.map[name]
    this.map[name] = oldValue ? oldValue+','+value : value
  }

  Headers.prototype['delete'] = function(name) {
    delete this.map[normalizeName(name)]
  }

  Headers.prototype.get = function(name) {
    name = normalizeName(name)
    return this.has(name) ? this.map[name] : null
  }

  Headers.prototype.has = function(name) {
    return this.map.hasOwnProperty(normalizeName(name))
  }

  Headers.prototype.set = function(name, value) {
    this.map[normalizeName(name)] = normalizeValue(value)
  }

  Headers.prototype.forEach = function(callback, thisArg) {
    for (var name in this.map) {
      if (this.map.hasOwnProperty(name)) {
        callback.call(thisArg, this.map[name], name, this)
      }
    }
  }

  Headers.prototype.keys = function() {
    var items = []
    this.forEach(function(value, name) { items.push(name) })
    return iteratorFor(items)
  }

  Headers.prototype.values = function() {
    var items = []
    this.forEach(function(value) { items.push(value) })
    return iteratorFor(items)
  }

  Headers.prototype.entries = function() {
    var items = []
    this.forEach(function(value, name) { items.push([name, value]) })
    return iteratorFor(items)
  }

  if (support.iterable) {
    Headers.prototype[Symbol.iterator] = Headers.prototype.entries
  }

  function consumed(body) {
    if (body.bodyUsed) {
      return Promise.reject(new TypeError('Already read'))
    }
    body.bodyUsed = true
  }

  function fileReaderReady(reader) {
    return new Promise(function(resolve, reject) {
      reader.onload = function() {
        resolve(reader.result)
      }
      reader.onerror = function() {
        reject(reader.error)
      }
    })
  }

  function readBlobAsArrayBuffer(blob) {
    var reader = new FileReader()
    var promise = fileReaderReady(reader)
    reader.readAsArrayBuffer(blob)
    return promise
  }

  function readBlobAsText(blob) {
    var reader = new FileReader()
    var promise = fileReaderReady(reader)
    reader.readAsText(blob)
    return promise
  }

  function readArrayBufferAsText(buf) {
    var view = new Uint8Array(buf)
    var chars = new Array(view.length)

    for (var i = 0; i < view.length; i++) {
      chars[i] = String.fromCharCode(view[i])
    }
    return chars.join('')
  }

  function bufferClone(buf) {
    if (buf.slice) {
      return buf.slice(0)
    } else {
      var view = new Uint8Array(buf.byteLength)
      view.set(new Uint8Array(buf))
      return view.buffer
    }
  }

  function Body() {
    this.bodyUsed = false

    this._initBody = function(body) {
      this._bodyInit = body
      if (!body) {
        this._bodyText = ''
      } else if (typeof body === 'string') {
        this._bodyText = body
      } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
        this._bodyBlob = body
      } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
        this._bodyFormData = body
      } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
        this._bodyText = body.toString()
      } else if (support.arrayBuffer && support.blob && isDataView(body)) {
        this._bodyArrayBuffer = bufferClone(body.buffer)
        // IE 10-11 can't handle a DataView body.
        this._bodyInit = new Blob([this._bodyArrayBuffer])
      } else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
        this._bodyArrayBuffer = bufferClone(body)
      } else {
        throw new Error('unsupported BodyInit type')
      }

      if (!this.headers.get('content-type')) {
        if (typeof body === 'string') {
          this.headers.set('content-type', 'text/plain;charset=UTF-8')
        } else if (this._bodyBlob && this._bodyBlob.type) {
          this.headers.set('content-type', this._bodyBlob.type)
        } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
          this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')
        }
      }
    }

    if (support.blob) {
      this.blob = function() {
        var rejected = consumed(this)
        if (rejected) {
          return rejected
        }

        if (this._bodyBlob) {
          return Promise.resolve(this._bodyBlob)
        } else if (this._bodyArrayBuffer) {
          return Promise.resolve(new Blob([this._bodyArrayBuffer]))
        } else if (this._bodyFormData) {
          throw new Error('could not read FormData body as blob')
        } else {
          return Promise.resolve(new Blob([this._bodyText]))
        }
      }

      this.arrayBuffer = function() {
        if (this._bodyArrayBuffer) {
          return consumed(this) || Promise.resolve(this._bodyArrayBuffer)
        } else {
          return this.blob().then(readBlobAsArrayBuffer)
        }
      }
    }

    this.text = function() {
      var rejected = consumed(this)
      if (rejected) {
        return rejected
      }

      if (this._bodyBlob) {
        return readBlobAsText(this._bodyBlob)
      } else if (this._bodyArrayBuffer) {
        return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer))
      } else if (this._bodyFormData) {
        throw new Error('could not read FormData body as text')
      } else {
        return Promise.resolve(this._bodyText)
      }
    }

    if (support.formData) {
      this.formData = function() {
        return this.text().then(decode)
      }
    }

    this.json = function() {
      return this.text().then(JSON.parse)
    }

    return this
  }

  // HTTP methods whose capitalization should be normalized
  var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']

  function normalizeMethod(method) {
    var upcased = method.toUpperCase()
    return (methods.indexOf(upcased) > -1) ? upcased : method
  }

  function Request(input, options) {
    options = options || {}
    var body = options.body

    if (typeof input === 'string') {
      this.url = input
    } else {
      if (input.bodyUsed) {
        throw new TypeError('Already read')
      }
      this.url = input.url
      this.credentials = input.credentials
      if (!options.headers) {
        this.headers = new Headers(input.headers)
      }
      this.method = input.method
      this.mode = input.mode
      if (!body && input._bodyInit != null) {
        body = input._bodyInit
        input.bodyUsed = true
      }
    }

    this.credentials = options.credentials || this.credentials || 'omit'
    if (options.headers || !this.headers) {
      this.headers = new Headers(options.headers)
    }
    this.method = normalizeMethod(options.method || this.method || 'GET')
    this.mode = options.mode || this.mode || null
    this.referrer = null

    if ((this.method === 'GET' || this.method === 'HEAD') && body) {
      throw new TypeError('Body not allowed for GET or HEAD requests')
    }
    this._initBody(body)
  }

  Request.prototype.clone = function() {
    return new Request(this, { body: this._bodyInit })
  }

  function decode(body) {
    var form = new FormData()
    body.trim().split('&').forEach(function(bytes) {
      if (bytes) {
        var split = bytes.split('=')
        var name = split.shift().replace(/\+/g, ' ')
        var value = split.join('=').replace(/\+/g, ' ')
        form.append(decodeURIComponent(name), decodeURIComponent(value))
      }
    })
    return form
  }

  function parseHeaders(rawHeaders) {
    var headers = new Headers()
    rawHeaders.split('\r\n').forEach(function(line) {
      var parts = line.split(':')
      var key = parts.shift().trim()
      if (key) {
        var value = parts.join(':').trim()
        headers.append(key, value)
      }
    })
    return headers
  }

  Body.call(Request.prototype)

  function Response(bodyInit, options) {
    if (!options) {
      options = {}
    }

    this.type = 'default'
    this.status = 'status' in options ? options.status : 200
    this.ok = this.status >= 200 && this.status < 300
    this.statusText = 'statusText' in options ? options.statusText : 'OK'
    this.headers = new Headers(options.headers)
    this.url = options.url || ''
    this._initBody(bodyInit)
  }

  Body.call(Response.prototype)

  Response.prototype.clone = function() {
    return new Response(this._bodyInit, {
      status: this.status,
      statusText: this.statusText,
      headers: new Headers(this.headers),
      url: this.url
    })
  }

  Response.error = function() {
    var response = new Response(null, {status: 0, statusText: ''})
    response.type = 'error'
    return response
  }

  var redirectStatuses = [301, 302, 303, 307, 308]

  Response.redirect = function(url, status) {
    if (redirectStatuses.indexOf(status) === -1) {
      throw new RangeError('Invalid status code')
    }

    return new Response(null, {status: status, headers: {location: url}})
  }

  self.Headers = Headers
  self.Request = Request
  self.Response = Response

  self.fetch = function(input, init) {
    return new Promise(function(resolve, reject) {
      var request = new Request(input, init)
      var xhr = new XMLHttpRequest()

      xhr.onload = function() {
        var options = {
          status: xhr.status,
          statusText: xhr.statusText,
          headers: parseHeaders(xhr.getAllResponseHeaders() || '')
        }
        options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL')
        var body = 'response' in xhr ? xhr.response : xhr.responseText
        resolve(new Response(body, options))
      }

      xhr.onerror = function() {
        reject(new TypeError('Network request failed'))
      }

      xhr.ontimeout = function() {
        reject(new TypeError('Network request failed'))
      }

      xhr.open(request.method, request.url, true)

      if (request.credentials === 'include') {
        xhr.withCredentials = true
      }

      if ('responseType' in xhr && support.blob) {
        xhr.responseType = 'blob'
      }

      request.headers.forEach(function(value, name) {
        xhr.setRequestHeader(name, value)
      })

      xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
    })
  }
  self.fetch.polyfill = true
})(typeof self !== 'undefined' ? self : this);
<|endoftext|>


<commit_before>'use strict';

var Slack            = require('slack-node');
var winston          = require('winston');
var awsRegions       = require(__dirname + '/awsRegions.js');
var StatusFeed       = require(__dirname + '/statusFeed.js');
var statusFeedParser = require(__dirname + '/statusFeedParser.js');

function Constructor(rssFeed, slackConfigs) {
  var integrations = [];

  // Initialization helper
  (function () {
    var i;
    var j;
    var newIntegration;
    var optionalKeys = [];
    var Integration = function () {
      return {
        iconUrl: 'http://i.imgur.com/XhzVhKC.png',
        username: 'AWS Service Status',
        includeRegions: awsRegions.slice(),
        excludeRegions: [],
        includeServices: [],
        excludeServices: [],
        channel: null
      };
    };

    for (i = 0; i < slackConfigs.length; i++ ) {
      newIntegration = new Integration();
      optionalKeys = Object.keys(newIntegration);
      newIntegration.slack = new Slack();
      if (slackConfigs[i].hasOwnProperty('webHookUri')) {
        newIntegration.slack.setWebhook(slackConfigs[i].webHookUri);
      } else {
        throw new Error('Slack Config missing required property "webHookUri"');
      }
      newIntegration.awsSvcStatusFeed = new StatusFeed();
      for (j = 0; j < optionalKeys.length; j++ ) {
        if (slackConfigs[i].hasOwnProperty(optionalKeys[j])) {
          newIntegration[optionalKeys[j]] =
            slackConfigs[i][optionalKeys[j]];
        }
      }
      winston.log('info', 'Configured integration: ' + newIntegration);
      integrations.push(newIntegration);
    }
  })();

  this.awsServiceStatusFetch = function(done) {
    statusFeedParser(rssFeed, function (err, unprocessedItems) {
      var stillProcessing = integrations.length;
      var preProcessedItemCount = 0;
      if (err) {
        winston.log('error', err);
        if (typeof(done) === 'function') {
          done(err, null);
        }
      } else {
        winston.log('info', unprocessedItems.length +
          ' RSS items fetched from ' + rssFeed);
        integrations.forEach(function (integration) {
          function filterItem(statusItem) {
            var region = statusItem.region();
            var service = statusItem.service();
            if (integration.excludeRegions.indexOf(region) >= 0 ||
                integration.excludeServices.indexOf(service) >= 0) {
              return false;
            }
            if ((region === 'global' ||
                 integration.includeRegions.indexOf(region) >= 0) &&
                (integration.includeServices.length === 0 ||
                 integration.includeServices.indexOf(service) >=0 )) {
              return true;
            }
            return false;
          }
          preProcessedItemCount +=
            integration.awsSvcStatusFeed.preProcess(
              unprocessedItems.slice(), filterItem);
          if (--stillProcessing === 0) {
            done(null, preProcessedItemCount);
          }
        });
      }
    });
  };

  this.awsServiceStatusProcess = function (done) {
    var stillProcessing = integrations.length;
    var slackMessagesSent = 0;
    integrations.forEach(function (integration) {
      winston.log('info', 'Processing pending statuses for ' +
        integration.slack.webhookUrl);

      function slackItemHandler(statusItem, cb, itemsLeft) {
        var slackParams;

        // if not status item is set, we have nothing to process
        if (! statusItem) {
          winston.log('debug', 'No Pending messages for ' +
            integration.slack.webhookUrl);

          if (--stillProcessing === 0 && typeof(done) === 'function') {
            done(null, slackMessagesSent);
          }
          return cb();
        }

        slackParams = {
          username: integration.username,
          /*jshint -W106*/
          icon_emoji: integration.iconUrl,
          /*jshint +W106*/
          attachments: statusItem.getSlackAttachments()
        };

        if (integration.channel) {
          slackParams.channel = integration.channel;
        }
        integration.slack.webhook(slackParams, function (err, res) {
          if (err) { winston.log('error', err); }
          else {
            winston.log('debug', res);
            winston.log('info', statusItem.guid() + ' sent to ' +
              integration.slack.webhookUrl);
            ++slackMessagesSent;
          }
          if (itemsLeft === 0) {
            winston.log('debug', 'Processing complete for ' +
              integration.slack.webhookUrl);
            if (--stillProcessing === 0 && typeof(done) === 'function') {
              done(null, slackMessagesSent);
            }
          }
          return cb(err, statusItem);
        });
      }

      integration.awsSvcStatusFeed.processPending(slackItemHandler);
    });
  };

  this.purgeItemStatus = function () {
    // for each
    // awsBlah.purgeItemStatus()
    //
    winston.log('debug', 'Purge stuff');
  };
}

module.exports = Constructor;
<commit_msg>Only call callback if it is passed<commit_after>'use strict';

var Slack            = require('slack-node');
var winston          = require('winston');
var awsRegions       = require(__dirname + '/awsRegions.js');
var StatusFeed       = require(__dirname + '/statusFeed.js');
var statusFeedParser = require(__dirname + '/statusFeedParser.js');

function Constructor(rssFeed, slackConfigs) {
  var integrations = [];

  // Initialization helper
  (function () {
    var i;
    var j;
    var newIntegration;
    var optionalKeys = [];
    var Integration = function () {
      return {
        iconUrl: 'http://i.imgur.com/XhzVhKC.png',
        username: 'AWS Service Status',
        includeRegions: awsRegions.slice(),
        excludeRegions: [],
        includeServices: [],
        excludeServices: [],
        channel: null
      };
    };

    for (i = 0; i < slackConfigs.length; i++ ) {
      newIntegration = new Integration();
      optionalKeys = Object.keys(newIntegration);
      newIntegration.slack = new Slack();
      if (slackConfigs[i].hasOwnProperty('webHookUri')) {
        newIntegration.slack.setWebhook(slackConfigs[i].webHookUri);
      } else {
        throw new Error('Slack Config missing required property "webHookUri"');
      }
      newIntegration.awsSvcStatusFeed = new StatusFeed();
      for (j = 0; j < optionalKeys.length; j++ ) {
        if (slackConfigs[i].hasOwnProperty(optionalKeys[j])) {
          newIntegration[optionalKeys[j]] =
            slackConfigs[i][optionalKeys[j]];
        }
      }
      winston.log('info', 'Configured integration: ' + newIntegration);
      integrations.push(newIntegration);
    }
  })();

  this.awsServiceStatusFetch = function(done) {
    statusFeedParser(rssFeed, function (err, unprocessedItems) {
      var stillProcessing = integrations.length;
      var preProcessedItemCount = 0;
      if (err) {
        winston.log('error', err);
        if (typeof(done) === 'function') {
          done(err, null);
        }
      } else {
        winston.log('info', unprocessedItems.length +
          ' RSS items fetched from ' + rssFeed);
        integrations.forEach(function (integration) {
          function filterItem(statusItem) {
            var region = statusItem.region();
            var service = statusItem.service();
            if (integration.excludeRegions.indexOf(region) >= 0 ||
                integration.excludeServices.indexOf(service) >= 0) {
              return false;
            }
            if ((region === 'global' ||
                 integration.includeRegions.indexOf(region) >= 0) &&
                (integration.includeServices.length === 0 ||
                 integration.includeServices.indexOf(service) >=0 )) {
              return true;
            }
            return false;
          }
          preProcessedItemCount +=
            integration.awsSvcStatusFeed.preProcess(
              unprocessedItems.slice(), filterItem);
          if (--stillProcessing === 0 && typeof(done) === 'function') {
            done(null, preProcessedItemCount);
          }
        });
      }
    });
  };

  this.awsServiceStatusProcess = function (done) {
    var stillProcessing = integrations.length;
    var slackMessagesSent = 0;
    integrations.forEach(function (integration) {
      winston.log('info', 'Processing pending statuses for ' +
        integration.slack.webhookUrl);

      function slackItemHandler(statusItem, cb, itemsLeft) {
        var slackParams;

        // if not status item is set, we have nothing to process
        if (! statusItem) {
          winston.log('debug', 'No Pending messages for ' +
            integration.slack.webhookUrl);

          if (--stillProcessing === 0 && typeof(done) === 'function') {
            done(null, slackMessagesSent);
          }
          return cb();
        }

        slackParams = {
          username: integration.username,
          /*jshint -W106*/
          icon_emoji: integration.iconUrl,
          /*jshint +W106*/
          attachments: statusItem.getSlackAttachments()
        };

        if (integration.channel) {
          slackParams.channel = integration.channel;
        }
        integration.slack.webhook(slackParams, function (err, res) {
          if (err) { winston.log('error', err); }
          else {
            winston.log('debug', res);
            winston.log('info', statusItem.guid() + ' sent to ' +
              integration.slack.webhookUrl);
            ++slackMessagesSent;
          }
          if (itemsLeft === 0) {
            winston.log('debug', 'Processing complete for ' +
              integration.slack.webhookUrl);
            if (--stillProcessing === 0 && typeof(done) === 'function') {
              done(null, slackMessagesSent);
            }
          }
          return cb(err, statusItem);
        });
      }

      integration.awsSvcStatusFeed.processPending(slackItemHandler);
    });
  };

  this.purgeItemStatus = function () {
    // for each
    // awsBlah.purgeItemStatus()
    //
    winston.log('debug', 'Purge stuff');
  };
}

module.exports = Constructor;
<|endoftext|>


<commit_before>const is = require('is');
const Promise = require('bluebird');

module.exports = [
  {
    point: 'preRequest',
    handler: (route, request) => {
      request.auditLog = { start: process.hrtime() };
      return Promise.resolve([route, request]);
    },
  },
  {
    point: 'preResponse',
    handler: function preResponse(error, result, request) {
      const service = this;
      const execTime = request.auditLog.execTime = process.hrtime(request.auditLog.start);

      const meta = {
        route: request.route,
        params: request.params,
        latency: (execTime[0] * 1000) + (+(execTime[1] / 1000000).toFixed(3)),
      };

      if (error) {
        const err = is.fn(error.toJSON) ? error.toJSON() : error.toString();
        service.log.error(meta, 'Error performing operation', err);
      } else {
        service.log.info(meta, 'completed operation', service._config.debug ? result : '');
      }

      return Promise.resolve([error, result]);
    },
  },
];
<commit_msg>feat: verbose log, include more input args<commit_after>const is = require('is');
const Promise = require('bluebird');

module.exports = [
  {
    point: 'preRequest',
    handler: (route, request) => {
      request.auditLog = { start: process.hrtime() };
      return Promise.resolve([route, request]);
    },
  },
  {
    point: 'preResponse',
    handler: function preResponse(error, result, request) {
      const service = this;
      const execTime = request.auditLog.execTime = process.hrtime(request.auditLog.start);

      const meta = {
        route: request.route,
        params: request.params,
        method: request.method,
        transport: request.transport,
        headers: request.headers,
        query: request.query,
        latency: (execTime[0] * 1000) + (+(execTime[1] / 1000000).toFixed(3)),
      };

      if (error) {
        const err = is.fn(error.toJSON) ? error.toJSON() : error.toString();
        service.log.error(meta, 'Error performing operation', err);
      } else {
        service.log.info(meta, 'completed operation', service._config.debug ? result : '');
      }

      return Promise.resolve([error, result]);
    },
  },
];
<|endoftext|>


<commit_before>mini.Module(
	"bloob/scenes/editorscene"
)
.requires(
	"bloob/scenes/mapscene",
	"engine/scene",
	"basic/mouse",
	"basic/utils",
	"basic/interactionhandler",
	"basic/mapbuilder",
	"basic/map"
)
.defines(function(MapScene, Scene, Mouse, Utils, InteractionHandler, MapBuilder, Map) {
	var EditorScene = MapScene.subclass({
		initialize: function(game, loop) {
			// call parent
			MapScene.prototype.initialize.apply(this, arguments);

			// test for map to json conversion
			var that = this;
			var toJson = {
				"toJson": function() {
					console.log(that.map.toJson());
				}
			};
			this.datGuiFolder
				.add(toJson, "toJson").name("PRINT AS JSON");
		},
		update: function(timePassed) {
			// rendering
			this.camera.update(timePassed);
			this.renderer.draw(timePassed);
			// interaction
			this.mouse.update(timePassed);
		},
		initMouseInteraction: function() {
			var that = this;

			// interaction techniques
			var setSpawnPoint = new InteractionHandler();
			var createBody = new InteractionHandler()
				.name("CREATE BODY")
				.onPressed(function(timePassed, mouse) {
					Jello.BodyFactory.createBluePrint(Jello.SpringBody)
						.world(that.world)
						.shape(new Jello.ClosedShape()
							.begin()
							.addVertex(new Jello.Vector2(-1, -1))
							.addVertex(new Jello.Vector2(-1,  1))
							.addVertex(new Jello.Vector2( 1,  1))
							.addVertex(new Jello.Vector2( 1, -1))
							.finish())
						.pointMasses(1)
						.translate(that.camera.screenToWorldCoordinates(mouse.input.mouse))
						.rotate(0)
						.scale(Jello.Vector2.One.copy())
						.isKinematic(false)
						.edgeSpringK(300.0)
						.edgeSpringDamp(5.0)
						.shapeSpringK(150.0)
						.shapeSpringDamp(5.0)
						.addInternalSpring(0, 2, 300, 10)
						.addInternalSpring(1, 3, 300, 10)
						.build();
				});
			var moveBody = new InteractionHandler()
				.name("MOVE BODY")
				.context({
					"camera": this.camera,
					"world": this.world,
					"body": undefined,
					"screenStartCoordinates": Jello.Vector2.Zero.copy(),
					"screenCurrentCoordinates": Jello.Vector2.Zero.copy()
				})
				.onPressed(function(timePassed, mouse) {
					// remenber body to move
					var answer = this.world.getClosestPointMass(this.camera.screenToWorldCoordinates(mouse.input.mouse));
					this.body = this.world.getBody(answer.bodyId);

					// remember start coordinate
					this.screenStartCoordinates.set(mouse.input.mouse);
					this.screenCurrentCoordinates = this.screenStartCoordinates.copy();
				})
				.onState(function(timePassed, mouse) {
					if(typeof this.body !== "undefined") {
						// add the offset to the previous step of the cursor
						// to the body position (translated in world coordinates)
						var cursorOffsetInWorld = this.camera.screenToWorldCoordinates(mouse.input.mouse)
							.sub(this.camera.screenToWorldCoordinates(this.screenCurrentCoordinates));
						var pos = this.body.getDerivedPosition().copy().add(cursorOffsetInWorld);
						var angleInRadians = this.body.getDerivedAngle();
						var scale = this.body.getScale();

						// actual update of position (leave angle and scale unchanged)
						this.body.setPositionAngle(pos, angleInRadians, scale);

						// remember current coordinates
						this.screenCurrentCoordinates.set(mouse.input.mouse);

						// adjustments for rendering
						this.body.updateAABB(0, true);
					};
				});
			var deleteBody = new InteractionHandler()
				.name("DELETE BODY")
				.context({
					"camera": this.camera,
					"world": this.world
				})
				.onPressed(function(timePassed, mouse) {
					var answer = this.world.getClosestPointMass(this.camera.screenToWorldCoordinates(mouse.input.mouse));
					var body = this.world.getBody(answer.bodyId);
					this.world.removeBody(body);
				});
			var createPointMass = new InteractionHandler()
				.name("CREATE POINT MASS")
				.context({
					"camera": this.camera,
					"world": this.world
				})
				.onPressed(function(timePassed, mouse) {
					var answer = this.world.getClosestPointMass(this.camera.screenToWorldCoordinates(mouse.input.mouse));
					console.log(answer);
					var body = this.world.getBody(answer.bodyId);
					var baseShape = body.getBaseShape();
					body.setShape(baseShape.addVertex(new Jello.Vector2(0,0)));
				});
			var movePointMass = new InteractionHandler()
				.name("MOVE POINT MASS")
				.context({
					"camera": this.camera,
					"world": this.world,
					"body": undefined,
					"pointMassId": 0,
					"screenCurrentCoordinates": Jello.Vector2.Zero.copy()
				})
				.onPressed(function(timePassed, mouse) {
					var answer = this.world.getClosestPointMass(this.camera.screenToWorldCoordinates(mouse.input.mouse));
					this.body = this.world.getBody(answer.bodyId);
					this.pointMassId = answer.pointMassId;

					// remember current coordinates
					this.screenCurrentCoordinates.set(mouse.input.mouse);
				})
				.onState(function(timePassed, mouse) {
					var angleInRadians = -this.body.getDerivedAngle();
					var cursorOffsetInWorld = Jello.VectorTools.rotateVector(
						this.camera.screenToWorldCoordinates(mouse.input.mouse)
							.sub(this.camera.screenToWorldCoordinates(this.screenCurrentCoordinates)),
						Math.cos(angleInRadians),
						Math.sin(angleInRadians)
					).divVector(this.body.getScale());

					var baseShape = this.body.getBaseShape();
					baseShape.getVertices()[this.pointMassId].addSelf(cursorOffsetInWorld);
					this.body.setShape(baseShape, true);

					// remember current coordinates
					this.screenCurrentCoordinates.set(mouse.input.mouse);

					// adjustments for rendering
					this.body.updateAABB(0, true);
				});
			var deletePointMass = new InteractionHandler()
				.name("DELETE POINT MASS")
				.context({
					"camera": this.camera,
					"world": this.world
				})
				.onPressed(function(timePassed, mouse) {
					var answer = this.world.getClosestPointMass(this.camera.screenToWorldCoordinates(mouse.input.mouse));
					var body = this.world.getBody(answer.bodyId);
					var pointMassId = answer.pointMassId;
					var baseShape = body.getBaseShape();
					// do not delete the last point mass
					if(baseShape.getVertices().length > 1) {
						baseShape.mLocalVertices.splice( pointMassId, 1 );
						body.setShape(baseShape);
					};
				});
			var moveCamera = new InteractionHandler()
				.name("MOVE CAMERA")
				.context({
					"camera": this.camera,
					"screenStartCoordinates": Jello.Vector2.Zero.copy(),
					"screenCurrentCoordinates": Jello.Vector2.Zero.copy()
				})
				.onPressed(function(timePassed, mouse) {
					// init start position and current position to the same value
					this.screenStartCoordinates = new Jello.Vector2(
							mouse.input.mouse.x,
							mouse.input.mouse.y
						);
					this.screenCurrentCoordinates = this.screenStartCoordinates.copy();
				})
				.onState(function(timePassed, mouse) {
					// retranslate back to starting point
					this.camera.translateBy(
						this.camera.screenToWorldCoordinates(this.screenCurrentCoordinates).sub(
							this.camera.screenToWorldCoordinates(this.screenStartCoordinates)
						)
					);
					// update current coordinates
					this.screenCurrentCoordinates.set(mouse.input.mouse);
					// actual translation from starting point
					this.camera.translateBy(
						this.camera.screenToWorldCoordinates(this.screenStartCoordinates).sub(
							this.camera.screenToWorldCoordinates(this.screenCurrentCoordinates)
						)
					);
				});
			var goToMapTechnique = new InteractionHandler()
				.name("TEST MAP")
				.onPressed(function(timePassed, mouse) {
					console.log("Test MAP");
					that.stop();

					var newMapScene = new MapScene(that.game, that.loop);
					newMapScene
						.onMapLoaded(
							Utils.bind(function blubmapLoaded() {
								MapBuilder.setUpTestMap(this);
								this.map.spawnPlayerAt(this, this.datGuiFolder);
								this.run();
							}, newMapScene)
						)
						.loadMap(that.game.config.startLevel);
				});

			var interactionTechniquesforDatGui = [
				setSpawnPoint,
				createBody,
				moveBody,
				deleteBody,
				createPointMass,
				movePointMass,
				deletePointMass,
				// TODO: create, delete Springs
				moveCamera,
				goToMapTechnique
			];

			var mouse = new Mouse(this.game.canvas)
				.onLeftClick(movePointMass)
				.onRightClick(moveBody)
				.initDatGui(this.datGuiFolder, interactionTechniquesforDatGui);

			return mouse;
		},

		testChangeMap: function() {
			console.log(arguments);
			this.game.datGui.removeFolder(this.sceneID);
			this.stop();

			var mapScene = new MapScene(this.game, this.loop);
			Map.fromJson(this.map.toJson(), mapScene.map);
			mapScene.map.spawnPlayerAt(mapScene, mapScene.datGuiFolder);
			mapScene.run();
		}
	});

	return EditorScene;
});
<commit_msg>added MapToJsonConverter module as dependency to EditorScene<commit_after>mini.Module(
	"bloob/scenes/editorscene"
)
.requires(
	"bloob/scenes/mapscene",
	"engine/scene",
	"basic/mouse",
	"basic/utils",
	"basic/interactionhandler",
	"basic/mapbuilder",
	"basic/map",
	"assets/converter/tojson/maptojsonconverter"
)
.defines(function(MapScene, Scene, Mouse, Utils, InteractionHandler, MapBuilder, Map, MapToJsonConverter) {
	var EditorScene = MapScene.subclass({
		initialize: function(game, loop) {
			// call parent
			MapScene.prototype.initialize.apply(this, arguments);

			// test for map to json conversion
			var that = this;
			var toJson = {
				"toJson": function() {
					console.log(that.map.toJson());
				}
			};
			this.datGuiFolder
				.add(toJson, "toJson").name("PRINT AS JSON");
		},

		update: function(timePassed) {
			// rendering
			this.camera.update(timePassed);
			this.renderer.draw(timePassed);
			// interaction
			this.mouse.update(timePassed);
		},

		initMouseInteraction: function() {
			var that = this;

			// interaction techniques
			var setSpawnPoint = new InteractionHandler();
			var createBody = new InteractionHandler()
				.name("CREATE BODY")
				.onPressed(function(timePassed, mouse) {
					Jello.BodyFactory.createBluePrint(Jello.SpringBody)
						.world(that.world)
						.shape(new Jello.ClosedShape()
							.begin()
							.addVertex(new Jello.Vector2(-1, -1))
							.addVertex(new Jello.Vector2(-1,  1))
							.addVertex(new Jello.Vector2( 1,  1))
							.addVertex(new Jello.Vector2( 1, -1))
							.finish())
						.pointMasses(1)
						.translate(that.camera.screenToWorldCoordinates(mouse.input.mouse))
						.rotate(0)
						.scale(Jello.Vector2.One.copy())
						.isKinematic(false)
						.edgeSpringK(300.0)
						.edgeSpringDamp(5.0)
						.shapeSpringK(150.0)
						.shapeSpringDamp(5.0)
						.addInternalSpring(0, 2, 300, 10)
						.addInternalSpring(1, 3, 300, 10)
						.build();
				});
			var moveBody = new InteractionHandler()
				.name("MOVE BODY")
				.context({
					"camera": this.camera,
					"world": this.world,
					"body": undefined,
					"screenStartCoordinates": Jello.Vector2.Zero.copy(),
					"screenCurrentCoordinates": Jello.Vector2.Zero.copy()
				})
				.onPressed(function(timePassed, mouse) {
					// remenber body to move
					var answer = this.world.getClosestPointMass(this.camera.screenToWorldCoordinates(mouse.input.mouse));
					this.body = this.world.getBody(answer.bodyId);

					// remember start coordinate
					this.screenStartCoordinates.set(mouse.input.mouse);
					this.screenCurrentCoordinates = this.screenStartCoordinates.copy();
				})
				.onState(function(timePassed, mouse) {
					if(typeof this.body !== "undefined") {
						// add the offset to the previous step of the cursor
						// to the body position (translated in world coordinates)
						var cursorOffsetInWorld = this.camera.screenToWorldCoordinates(mouse.input.mouse)
							.sub(this.camera.screenToWorldCoordinates(this.screenCurrentCoordinates));
						var pos = this.body.getDerivedPosition().copy().add(cursorOffsetInWorld);
						var angleInRadians = this.body.getDerivedAngle();
						var scale = this.body.getScale();

						// actual update of position (leave angle and scale unchanged)
						this.body.setPositionAngle(pos, angleInRadians, scale);

						// remember current coordinates
						this.screenCurrentCoordinates.set(mouse.input.mouse);

						// adjustments for rendering
						this.body.updateAABB(0, true);
					};
				});
			var deleteBody = new InteractionHandler()
				.name("DELETE BODY")
				.context({
					"camera": this.camera,
					"world": this.world
				})
				.onPressed(function(timePassed, mouse) {
					var answer = this.world.getClosestPointMass(this.camera.screenToWorldCoordinates(mouse.input.mouse));
					var body = this.world.getBody(answer.bodyId);
					this.world.removeBody(body);
				});
			var createPointMass = new InteractionHandler()
				.name("CREATE POINT MASS")
				.context({
					"camera": this.camera,
					"world": this.world
				})
				.onPressed(function(timePassed, mouse) {
					var answer = this.world.getClosestPointMass(this.camera.screenToWorldCoordinates(mouse.input.mouse));
					console.log(answer);
					var body = this.world.getBody(answer.bodyId);
					var baseShape = body.getBaseShape();
					body.setShape(baseShape.addVertex(new Jello.Vector2(0,0)));
				});
			var movePointMass = new InteractionHandler()
				.name("MOVE POINT MASS")
				.context({
					"camera": this.camera,
					"world": this.world,
					"body": undefined,
					"pointMassId": 0,
					"screenCurrentCoordinates": Jello.Vector2.Zero.copy()
				})
				.onPressed(function(timePassed, mouse) {
					var answer = this.world.getClosestPointMass(this.camera.screenToWorldCoordinates(mouse.input.mouse));
					this.body = this.world.getBody(answer.bodyId);
					this.pointMassId = answer.pointMassId;

					// remember current coordinates
					this.screenCurrentCoordinates.set(mouse.input.mouse);
				})
				.onState(function(timePassed, mouse) {
					var angleInRadians = -this.body.getDerivedAngle();
					var cursorOffsetInWorld = Jello.VectorTools.rotateVector(
						this.camera.screenToWorldCoordinates(mouse.input.mouse)
							.sub(this.camera.screenToWorldCoordinates(this.screenCurrentCoordinates)),
						Math.cos(angleInRadians),
						Math.sin(angleInRadians)
					).divVector(this.body.getScale());

					var baseShape = this.body.getBaseShape();
					baseShape.getVertices()[this.pointMassId].addSelf(cursorOffsetInWorld);
					this.body.setShape(baseShape, true);

					// remember current coordinates
					this.screenCurrentCoordinates.set(mouse.input.mouse);

					// adjustments for rendering
					this.body.updateAABB(0, true);
				});
			var deletePointMass = new InteractionHandler()
				.name("DELETE POINT MASS")
				.context({
					"camera": this.camera,
					"world": this.world
				})
				.onPressed(function(timePassed, mouse) {
					var answer = this.world.getClosestPointMass(this.camera.screenToWorldCoordinates(mouse.input.mouse));
					var body = this.world.getBody(answer.bodyId);
					var pointMassId = answer.pointMassId;
					var baseShape = body.getBaseShape();
					// do not delete the last point mass
					if(baseShape.getVertices().length > 1) {
						baseShape.mLocalVertices.splice( pointMassId, 1 );
						body.setShape(baseShape);
					};
				});
			var moveCamera = new InteractionHandler()
				.name("MOVE CAMERA")
				.context({
					"camera": this.camera,
					"screenStartCoordinates": Jello.Vector2.Zero.copy(),
					"screenCurrentCoordinates": Jello.Vector2.Zero.copy()
				})
				.onPressed(function(timePassed, mouse) {
					// init start position and current position to the same value
					this.screenStartCoordinates = new Jello.Vector2(
							mouse.input.mouse.x,
							mouse.input.mouse.y
						);
					this.screenCurrentCoordinates = this.screenStartCoordinates.copy();
				})
				.onState(function(timePassed, mouse) {
					// retranslate back to starting point
					this.camera.translateBy(
						this.camera.screenToWorldCoordinates(this.screenCurrentCoordinates).sub(
							this.camera.screenToWorldCoordinates(this.screenStartCoordinates)
						)
					);
					// update current coordinates
					this.screenCurrentCoordinates.set(mouse.input.mouse);
					// actual translation from starting point
					this.camera.translateBy(
						this.camera.screenToWorldCoordinates(this.screenStartCoordinates).sub(
							this.camera.screenToWorldCoordinates(this.screenCurrentCoordinates)
						)
					);
				});
			var goToMapTechnique = new InteractionHandler()
				.name("TEST MAP")
				.onPressed(function(timePassed, mouse) {
					console.log("Test MAP");
					that.stop();

					var newMapScene = new MapScene(that.game, that.loop);
					newMapScene
						.onMapLoaded(
							Utils.bind(function blubmapLoaded() {
								MapBuilder.setUpTestMap(this);
								this.map.spawnPlayerAt(this, this.datGuiFolder);
								this.run();
							}, newMapScene)
						)
						.loadMap(that.game.config.startLevel);
				});

			var interactionTechniquesforDatGui = [
				setSpawnPoint,
				createBody,
				moveBody,
				deleteBody,
				createPointMass,
				movePointMass,
				deletePointMass,
				// TODO: create, delete Springs
				moveCamera,
				goToMapTechnique
			];

			var mouse = new Mouse(this.game.canvas)
				.onLeftClick(movePointMass)
				.onRightClick(moveBody)
				.initDatGui(this.datGuiFolder, interactionTechniquesforDatGui);

			return mouse;
		},

		testChangeMap: function() {
			console.log(arguments);
			this.game.datGui.removeFolder(this.sceneID);
			this.stop();

			var mapScene = new MapScene(this.game, this.loop);
			Map.fromJson(this.map.toJson(), mapScene.map);
			mapScene.map.spawnPlayerAt(mapScene, mapScene.datGuiFolder);
			mapScene.run();
		}
	});

	return EditorScene;
});
<|endoftext|>