<commit_before>/*
 * Google layer using Google Maps API
 */
//(function (google, L) {

L.Google = L.Class.extend({
	includes: L.Mixin.Events,

	options: {
		minZoom: 0,
		maxZoom: 18,
		tileSize: 256,
		subdomains: 'abc',
		errorTileUrl: '',
		attribution: '',
		opacity: 1,
		continuousWorld: false,
		noWrap: false
	},

	// Possible types: SATELLITE, ROADMAP, HYBRID, TERRAIN
	initialize: function(type, options) {
		L.Util.setOptions(this, options);

		this._ready = google.maps.Map != undefined;
		if (!this._ready) L.Google.asyncWait.push(this);

		this._type = type || 'SATELLITE';
	},

	onAdd: function(map, insertAtTheBottom) {
		this._map = map;
		this._insertAtTheBottom = insertAtTheBottom;

		// create a container div for tiles
		this._initContainer();
		this._initMapObject();

		// set up events
		map.on('viewreset', this._resetCallback, this);

		this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this);
		map.on('move', this._update, this);
		//map.on('moveend', this._update, this);

		map._controlCorners['bottomright'].style.marginBottom = "1em";

		this._reset();
		this._update();
	},

	onRemove: function(map) {
		this._map._container.removeChild(this._container);
		//this._container = null;

		this._map.off('viewreset', this._resetCallback, this);

		this._map.off('move', this._update, this);
		map._controlCorners['bottomright'].style.marginBottom = "0em";
		//this._map.off('moveend', this._update, this);
	},

	getAttribution: function() {
		return this.options.attribution;
	},

	setOpacity: function(opacity) {
		this.options.opacity = opacity;
		if (opacity < 1) {
			L.DomUtil.setOpacity(this._container, opacity);
		}
	},

	setElementSize: function(e, size) {
		e.style.width = size.x + "px";
		e.style.height = size.y + "px";
	},

	_initContainer: function() {
		var tilePane = this._map._container,
			first = tilePane.firstChild;

		if (!this._container) {
			this._container = L.DomUtil.create('div', 'leaflet-google-layer leaflet-top leaflet-left');
			this._container.id = "_GMapContainer_" + L.Util.stamp(this);
			this._container.style.zIndex = "auto";
		}

		if (true) {
			tilePane.insertBefore(this._container, first);

			this.setOpacity(this.options.opacity);
			this.setElementSize(this._container, this._map.getSize());
		}
	},

	_initMapObject: function() {
		if (!this._ready) return;
		this._google_center = new google.maps.LatLng(0, 0);
		var map = new google.maps.Map(this._container, {
		    center: this._google_center,
		    zoom: 0,
		    tilt: 0,
		    mapTypeId: google.maps.MapTypeId[this._type],
		    disableDefaultUI: true,
		    keyboardShortcuts: false,
		    draggable: false,
		    disableDoubleClickZoom: true,
		    scrollwheel: false,
		    streetViewControl: false
		});

		var _this = this;
		this._reposition = google.maps.event.addListenerOnce(map, "center_changed",
			function() { _this.onReposition(); });

		map.backgroundColor = '#ff0000';
		this._google = map;
	},

	_resetCallback: function(e) {
		this._reset(e.hard);
	},

	_reset: function(clearOldContainer) {
		this._initContainer();
	},

	_update: function() {
		if (!this._google) return;
		this._resize();

		var bounds = this._map.getBounds();
		var ne = bounds.getNorthEast();
		var sw = bounds.getSouthWest();
		var google_bounds = new google.maps.LatLngBounds(
			new google.maps.LatLng(sw.lat, sw.lng),
			new google.maps.LatLng(ne.lat, ne.lng)
		);
		var center = this._map.getCenter();
		var _center = new google.maps.LatLng(center.lat, center.lng);

		this._google.setCenter(_center);
		this._google.setZoom(this._map.getZoom());
		//this._google.fitBounds(google_bounds);
	},

	_resize: function() {
		var size = this._map.getSize();
		if (this._container.style.width == size.x &&
		    this._container.style.height == size.y)
			return;
		this.setElementSize(this._container, size);
		this.onReposition();
	},

	onReposition: function() {
		if (!this._google) return;
		google.maps.event.trigger(this._google, "resize");
	}
});

L.Google.asyncWait = [];
L.Google.asyncInitialize = function() {
	var i;
	for (i = 0; i < L.Google.asyncWait.length; i++) {
		var o = L.Google.asyncWait[i];
		o._ready = true;
		if (o._container) {
			o._initMapObject();
			o._update();
		}
	}
	L.Google.asyncWait = [];
}
//})(window.google, L)
<commit_msg>Better synchronisation of leaflet and Google Maps map move and zoom<commit_after>/*
 * Google layer using Google Maps API
 */
//(function (google, L) {

L.Google = L.Class.extend({
	includes: L.Mixin.Events,

	options: {
		minZoom: 0,
		maxZoom: 18,
		tileSize: 256,
		subdomains: 'abc',
		errorTileUrl: '',
		attribution: '',
		opacity: 1,
		continuousWorld: false,
		noWrap: false
	},

	// Possible types: SATELLITE, ROADMAP, HYBRID, TERRAIN
	initialize: function(type, options) {
		L.Util.setOptions(this, options);

		this._ready = google.maps.Map != undefined;
		if (!this._ready) L.Google.asyncWait.push(this);

		this._type = type || 'SATELLITE';
	},

	onAdd: function(map, insertAtTheBottom) {
		this._map = map;
		this._insertAtTheBottom = insertAtTheBottom;

		// create a container div for tiles
		this._initContainer();
		this._initMapObject();

		// set up events
		map.on('viewreset', this._resetCallback, this);

		this._limitedUpdate = L.Util.limitExecByInterval(this._update, 150, this);
		map.on('move', this._update, this);

		map.on('zoomanim', function (e) {
			var center = e.center;
			var _center = new google.maps.LatLng(center.lat, center.lng);

			this._google.setCenter(_center);
			this._google.setZoom(e.zoom);
		}, this);

		map._controlCorners['bottomright'].style.marginBottom = "1em";

		this._reset();
		this._update();
	},

	onRemove: function(map) {
		this._map._container.removeChild(this._container);
		//this._container = null;

		this._map.off('viewreset', this._resetCallback, this);

		this._map.off('move', this._update, this);
		map._controlCorners['bottomright'].style.marginBottom = "0em";
		//this._map.off('moveend', this._update, this);
	},

	getAttribution: function() {
		return this.options.attribution;
	},

	setOpacity: function(opacity) {
		this.options.opacity = opacity;
		if (opacity < 1) {
			L.DomUtil.setOpacity(this._container, opacity);
		}
	},

	setElementSize: function(e, size) {
		e.style.width = size.x + "px";
		e.style.height = size.y + "px";
	},

	_initContainer: function() {
		var tilePane = this._map._container,
			first = tilePane.firstChild;

		if (!this._container) {
			this._container = L.DomUtil.create('div', 'leaflet-google-layer leaflet-top leaflet-left');
			this._container.id = "_GMapContainer_" + L.Util.stamp(this);
			this._container.style.zIndex = "auto";
		}

		if (true) {
			tilePane.insertBefore(this._container, first);

			this.setOpacity(this.options.opacity);
			this.setElementSize(this._container, this._map.getSize());
		}
	},

	_initMapObject: function() {
		if (!this._ready) return;
		this._google_center = new google.maps.LatLng(0, 0);
		var map = new google.maps.Map(this._container, {
		    center: this._google_center,
		    zoom: 0,
		    tilt: 0,
		    mapTypeId: google.maps.MapTypeId[this._type],
		    disableDefaultUI: true,
		    keyboardShortcuts: false,
		    draggable: false,
		    disableDoubleClickZoom: true,
		    scrollwheel: false,
		    streetViewControl: false
		});

		var _this = this;
		this._reposition = google.maps.event.addListenerOnce(map, "center_changed",
			function() { _this.onReposition(); });

		map.backgroundColor = '#ff0000';
		this._google = map;
	},

	_resetCallback: function(e) {
		this._reset(e.hard);
	},

	_reset: function(clearOldContainer) {
		this._initContainer();
	},

	_update: function(e) {
		if (!this._google) return;
		this._resize();

		var center = e && e.latlng ? e.latlng : this._map.getCenter();
		var _center = new google.maps.LatLng(center.lat, center.lng);

		this._google.setCenter(_center);
		this._google.setZoom(this._map.getZoom());
		//this._google.fitBounds(google_bounds);
	},

	_resize: function() {
		var size = this._map.getSize();
		if (this._container.style.width == size.x &&
		    this._container.style.height == size.y)
			return;
		this.setElementSize(this._container, size);
		this.onReposition();
	},

	onReposition: function() {
		if (!this._google) return;
		google.maps.event.trigger(this._google, "resize");
	}
});

L.Google.asyncWait = [];
L.Google.asyncInitialize = function() {
	var i;
	for (i = 0; i < L.Google.asyncWait.length; i++) {
		var o = L.Google.asyncWait[i];
		o._ready = true;
		if (o._container) {
			o._initMapObject();
			o._update();
		}
	}
	L.Google.asyncWait = [];
}
//})(window.google, L)
<|endoftext|>


<commit_before>// CKEditor-jQuery EditorBox plugin
// Called on a jQuery selector (should be a single object only)
// to initialize a CKEditor editor box in the place of the
// selected textarea: $("#edit").editorBox().  The textarea
// must have a unique id in order to function properly.
// editorBox():
// Initializes the object.  All other methods should
// only be called on an already-initialized box.
// editorBox('focus', [keepTrying])
//   Passes focus to the selected editor box.  Returns
//   true/false depending on whether the focus attempt was
//   successful.  If the editor box has not completely initialized
//   yet, then the focus will fail.  If keepTrying
//   is defined and true, the method will keep trying until
//   the focus attempt succeeds.
// editorBox('destroy')
//   Removes the CKEditor instance from the textarea.
// editorBox('toggle')
//   Toggles the CKEditor instance.  Switches back and forth between
//   the textarea and the CKEditor WYSIWYG.
// editorBox('get_code')
//   Returns the plaintext code contained in the textarea or WYSIGWYG.
// editorBox('set_code', code)
//   Sets the plaintext code content for the editor box.  Replaces ALL
//   content with the string value of code.
// editorBox('insert_code', code)
//   Inserts the string value of code at the current selection point.
// editorBox('create_link', options)
//   Creates an anchor link at the current selection point.  If anything
//   is selected, makes the selection a link, otherwise creates a link.
//   options.url is used for the href of the link, and options.title
//   will be the body of the link if no text is currently selected.

define([
  'i18nObj',
  'jquery',
  'compiled/editor/editorAccessibility', /* editorAccessibility */
  'INST', // for IE detection; need to handle links in a special way
  'ckeditor-all', // CKEditor
  'jqueryui/draggable' /* /\.draggable/ */,
  'jquery.instructure_misc_plugins' /* /\.indicate/ */,
  'vendor/jquery.scrollTo' /* /\.scrollTo/ */,
  'vendor/jquery.ba-tinypubsub',
  'vendor/scribd.view' /* scribd */
], function(I18nObj, $, EditorAccessibility, INST) {

  var enableBookmarking = !!INST.browser.ie;
  $(document).ready(function() {
    enableBookmarking = !!INST.browser.ie;
  });

  function EditorBoxList() {
    this._textareas = {};
    this._editors = {};
    this._editor_boxes = {};
  }

  $.extend(EditorBoxList.prototype, {
    _addEditorBox: function(id, box) {
      $.publish('editorBox/add', id, box);
      this._editor_boxes[id] = box;
      this._editors[id] = CKEDITOR.instances[id];
      this._textareas[id] = $("textarea#" + id);
    },
    _removeEditorBox: function(id) {
      delete this._editor_boxes[id];
      delete this._editors[id];
      delete this._textareas[id];
      $.publish('editorBox/remove', id);
      if ($.isEmptyObject(this._editors)) $.publish('editorBox/removeAll');
    },
    _getTextArea: function(id) {
      if(!this._textareas[id]) {
        this._textareas[id] = $("textarea#" + id);
      }
      return this._textareas[id];
    },
    _getEditor: function(id) {
      if(!this._editors[id]) {
        this._editors[id] = CKEDITOR.instances[id];
      }
      return this._editors[id];
    },
    _getEditorBox: function(id) {
      return this._editor_boxes[id];
    }
  });

  var $instructureEditorBoxList = new EditorBoxList();

  function EditorBox(id, search_url, submit_url, content_url, options) {
    options = $.extend({}, options);

    var $textarea = $("#" + id);
    $textarea.data('enable_bookmarking', enableBookmarking);
    var width = $textarea.width();
    if(width == 0) {
      width = $textarea.closest(":visible").width();
    }

    var extra_buttons = [];
    for(var idx in INST.editorButtons) {
      extra_buttons.push("instructure_external_button_" + INST.editorButtons[idx].id);
    }

    var toolbar = [
      {name: 'document', items: ['Print', 'Templates']},
      {name: 'clipboard', items: ['Cut', 'Copy', 'Paste', '-', 'Undo', 'Redo']},
      {name: 'editing', items: ['Find', 'Replace', '-', 'SelectAll', '-', 'Scayt']},
      {name: 'basicstyles', items: ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat']},
      {name: 'paragraph', items: ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock']},
      {name: 'links', items: ['instructure_links', 'Unlink']},
      {name: 'insert', items: ['Table', 'HorizontalRule', 'Smiley', 'SpecialChar', 'EqnEditor', 'instructure_image']},
      {name: 'styles', items: ['Styles', 'Format', 'Font', 'FontSize']},
      {name: 'colors', items: ['TextColor', 'BGColor']},
      {name: 'tools', items: ['Maximize', 'ShowBlocks']},
      {name: 'others', items: extra_buttons}
    ];

    var ckOptions = $.extend({
      allowedContent: true,
      startupFocus: options.focus,
      toolbar: toolbar,
      pasteFromWordRemoveFontStyles: false,
      pasteFromWordRemoveStyles: false,
      extraPlugins: 'instructure_external_tools,instructure_links,instructure_image',
      removePlugins: 'image',
      removeButtons: '',
      contentsCss: [CKEDITOR.getUrl('contents.css'), '/stylesheets/static/baseline.type.css'],
      on: {
        focus: function(evt) {
          var $editor = $(evt.editor.element);
          $(document).triggerHandler('editor_box_focus', $editor);
          $.publish('editorBox/focus', $editor);
        }
      }
    }, options.tinyOptions || {});

    CKEDITOR.replace($textarea[0], ckOptions);

    this._textarea =  $textarea;
    this._editor = null;
    this._id = id;
    this._searchURL = search_url;
    this._submitURL = submit_url;
    this._contentURL = content_url;
    $instructureEditorBoxList._addEditorBox(id, this);
  }

// --------------------------------------------------------------------

  var editorBoxIdCounter = 1;

  $.fn.editorBox = function(options, more_options) {
    var args = arguments;
    if(this.length > 1) {
      return this.each(function() {
        var $this = $(this);
        $this.editorBox.apply($this, args);
      });
    }

    var id = this.attr('id');
    if(typeof(options) == "string" && options != "create") {
      if(options == "get_code") {
        return this._getContentCode(more_options);
      } else if(options == "set_code") {
        this._setContentCode(more_options);
      } else if(options == "insert_code") {
        this._insertHTML(more_options);
      } else if(options == "create_link") {
        this._linkSelection(more_options);
      } else if(options == "focus") {
        return this._editorFocus(more_options);
      } else if(options == "toggle") {
        this._toggleView();
      } else if(options == "execute") {
        var arr = [];
        for(var idx = 1; idx < arguments.length; idx++) {
          arr.push(arguments[idx]);
        }
        return $.fn._execCommand.apply(this, arr);
      } else if(options == "destroy") {
        this._removeEditor(more_options);
      } else if(options == "is_dirty") {
        return $instructureEditorBoxList._getEditor(id).checkDirty();
      } else if(options == 'exists?') {
        return !!$instructureEditorBoxList._getEditor(id);
      }
      return this;
    }
    this.data('rich_text', true);
    if(!id) {
      id = 'editor_box_unique_id_' + editorBoxIdCounter++;
      this.attr('id', id);
    }
    if($instructureEditorBoxList._getEditor(id)) {
      this._setContentCode(this.val());
      return this;
    }
    var search_url = "";
    if(options && options.search_url) {
      search_url = options.search_url;
    }
    var box = new EditorBox(id, search_url, "", "", options);
    return this;
  };

  $.fn._execCommand = function() {
    var id = $(this).attr('id');
    var editor = $instructureEditorBoxList._getEditor(id);
    if(editor && editor.execCommand) {
      editor.execCommand.apply(editor, arguments);
    }
    return this;
  };

  $.fn._justGetCode = function() {
    var id = this.attr('id') || '';
    var content = '';
    try {
      content = $instructureEditorBoxList._getEditor(id).getData();
    } catch(e) {}
    return content;
  };

  $.fn._getContentCode = function(update) {
    if(update == true) {
      var content = this._justGetCode(); //""
      this._setContentCode(content);
    }
    return this._justGetCode();
  };

  $.fn._getSearchURL = function() {
    return $instructureEditorBoxList._getEditorBox(this.attr('id'))._searchURL;
  };

  $.fn._getSubmitURL = function() {
    return $instructureEditorBoxList._getEditorBox(this.attr('id'))._submitURL;
  };

  $.fn._getContentURL = function() {
    return $instructureEditorBoxList._getEditorBox(this.attr('id'))._contentURL;
  };

  $.fn._toggleView = function() {
    var id = this.attr('id');
    var editor = $instructureEditorBoxList._getEditor(id);
    if (editor) {
      editor.setMode(editor.mode === 'source' ? 'wysiwyg' : 'source');
    }
  };

  $.fn._removeEditor = function() {
    var id = this.attr('id');
    this.data('rich_text', false);
    var editor = $instructureEditorBoxList._getEditor(id);
    if (editor) {
      editor.destroy();
      $instructureEditorBoxList._removeEditorBox(id);
    }
  };

  $.fn._setContentCode = function(val) {
    var id = this.attr('id');
    var editor = $instructureEditorBoxList._getEditor(id);
    if (editor) {
      editor.setData(val, {
        callback: function() {
          $instructureEditorBoxList._getEditor(id).updateElement();
        }
      });
    }
  };

  $.fn._insertHTML = function(html) {
    var id = this.attr('id');
    var editor = $instructureEditorBoxList._getEditor(id);
    if (editor) {
      editor.insertHtml(html, 'unfiltered_html');
    }
  };

  $.fn._editorFocus = function() {
    var $element = this,
        id = $element.attr('id'),
        editor = $instructureEditorBoxList._getEditor(id);
    if(!editor ) {
      return false;
    }
    editor.focus();
    $.publish('editorBox/focus', $element);
    return true;
  };

  $.fn._linkSelection = function(options) {
    if(typeof(options) == "string") {
      options = {url: options};
    }
    var title = options.title;
    var url = options.url || "";
    if(url.match(/@/) && !url.match(/\//) && !url.match(/^mailto:/)) {
      url = "mailto:" + url;
    } else if(!url.match(/^\w+:\/\//) && !url.match(/^mailto:/) && !url.match(/^\//)) {
      url = "http://" + url;
    }
    var classes = options.classes || "";
    var defaultText = options.text || options.title || "Link";
    var target = options.target || null;
    var id = $(this).attr('id');
    if(url.indexOf("@") != -1) {
      options.file = false;
      options.image = false;
      if(url.indexOf("mailto:") != 0) {
        url = "mailto:" + url;
      }
    } else if (url.indexOf("/") == -1) {
      title = url;
      url = url.replace(/\s/g, "");
      url = location.href + url;
    }
    if(options.file) {
      classes += "instructure_file_link ";
    }
    if(options.scribdable) {
      classes += "instructure_scribd_file ";
    }
    var link_id = '';
    if(options.kaltura_entry_id && options.kaltura_media_type) {
      link_id = "media_comment_" + options.kaltura_entry_id;
      if(options.kaltura_media_type == 'video') {
        classes += "instructure_video_link ";
      } else {
        classes += "instructure_audio_link ";
      }
    }
    if(options.image) {
      classes += "instructure_image_thumbnail ";
    }
    classes = $.unique(classes.split(/\s+/)).join(" ");
    var selectionText = "";
    var editor = $instructureEditorBoxList._getEditor(id);
    if(enableBookmarking && this.data('last_bookmark')) {
      editor.getSelection().selectBookmarks(this.data('last_bookmark'));
    }
    var selection = editor.getSelection();
    var anchor = selection.getSelectedElement();
    while(anchor && anchor.getName() != 'A' && anchor.getName() != 'BODY' && anchor.getParent()) {
      anchor = anchor.getParent();
    }
    if(anchor && anchor.getName() != 'A') { anchor = null; }

    var selectedContent = selection.getSelectedText();
    if(!selectedContent || selectedContent == "") {
      if(anchor) {
        $(anchor).attr({
          href: url,
          title: title || '',
          id: link_id,
          'class': classes,
          target: target
        });
      } else {
        selectionText = defaultText;
        var $div = $("<div/>");
        $div.append($("<a/>", {id: link_id, target: target, title: title, href: url, 'class': classes}).text(selectionText));
        editor.insertHtml($div.html(), 'unfiltered_html');
      }
    } else {
      var $div = $("<div/>");
      $div.append($("<a/>", {target: (target || ''), title: (title || ''), href: url, 'class': classes, 'id': link_id}).text(selectedContent));
      editor.insertHtml($div.html(), 'unfiltered_html');
    }
  };

});
<commit_msg>CNS-551: Menu bar of the Redactor is lost when the user presses the buttons twice (New Outcome or New Group)<commit_after>// CKEditor-jQuery EditorBox plugin
// Called on a jQuery selector (should be a single object only)
// to initialize a CKEditor editor box in the place of the
// selected textarea: $("#edit").editorBox().  The textarea
// must have a unique id in order to function properly.
// editorBox():
// Initializes the object.  All other methods should
// only be called on an already-initialized box.
// editorBox('focus', [keepTrying])
//   Passes focus to the selected editor box.  Returns
//   true/false depending on whether the focus attempt was
//   successful.  If the editor box has not completely initialized
//   yet, then the focus will fail.  If keepTrying
//   is defined and true, the method will keep trying until
//   the focus attempt succeeds.
// editorBox('destroy')
//   Removes the CKEditor instance from the textarea.
// editorBox('toggle')
//   Toggles the CKEditor instance.  Switches back and forth between
//   the textarea and the CKEditor WYSIWYG.
// editorBox('get_code')
//   Returns the plaintext code contained in the textarea or WYSIGWYG.
// editorBox('set_code', code)
//   Sets the plaintext code content for the editor box.  Replaces ALL
//   content with the string value of code.
// editorBox('insert_code', code)
//   Inserts the string value of code at the current selection point.
// editorBox('create_link', options)
//   Creates an anchor link at the current selection point.  If anything
//   is selected, makes the selection a link, otherwise creates a link.
//   options.url is used for the href of the link, and options.title
//   will be the body of the link if no text is currently selected.

define([
  'i18nObj',
  'jquery',
  'compiled/editor/editorAccessibility', /* editorAccessibility */
  'INST', // for IE detection; need to handle links in a special way
  'ckeditor-all', // CKEditor
  'jqueryui/draggable' /* /\.draggable/ */,
  'jquery.instructure_misc_plugins' /* /\.indicate/ */,
  'vendor/jquery.scrollTo' /* /\.scrollTo/ */,
  'vendor/jquery.ba-tinypubsub',
  'vendor/scribd.view' /* scribd */
], function(I18nObj, $, EditorAccessibility, INST) {

  var enableBookmarking = !!INST.browser.ie;
  $(document).ready(function() {
    enableBookmarking = !!INST.browser.ie;
  });

  function EditorBoxList() {
    this._textareas = {};
    this._editors = {};
    this._editor_boxes = {};
  }

  $.extend(EditorBoxList.prototype, {
    _addEditorBox: function(id, box) {
      $.publish('editorBox/add', id, box);
      this._editor_boxes[id] = box;
      this._editors[id] = CKEDITOR.instances[id];
      this._textareas[id] = $("textarea#" + id);
    },
    _removeEditorBox: function(id) {
      delete this._editor_boxes[id];
      delete this._editors[id];
      delete this._textareas[id];
      $.publish('editorBox/remove', id);
      if ($.isEmptyObject(this._editors)) $.publish('editorBox/removeAll');
    },
    _getTextArea: function(id) {
      if(!this._textareas[id]) {
        this._textareas[id] = $("textarea#" + id);
      }
      return this._textareas[id];
    },
    _getEditor: function(id) {
      var textArea = this._editors[id];
      if(textArea){
        var real_text_area = $(document).find("#"+textArea.name);
        var cke = real_text_area.siblings(".cke");
        if(real_text_area.length > 0 && cke.length == 0){
          return null;
        }
      }
      if(!this._editors[id]) {
        this._editors[id] = CKEDITOR.instances[id];
      }
      return this._editors[id];
    },
    _getEditorBox: function(id) {
      return this._editor_boxes[id];
    }
  });

  var $instructureEditorBoxList = new EditorBoxList();

  function EditorBox(id, search_url, submit_url, content_url, options) {
    options = $.extend({}, options);

    var $textarea = $("#" + id);
    $textarea.data('enable_bookmarking', enableBookmarking);
    var width = $textarea.width();
    if(width == 0) {
      width = $textarea.closest(":visible").width();
    }

    var extra_buttons = [];
    for(var idx in INST.editorButtons) {
      extra_buttons.push("instructure_external_button_" + INST.editorButtons[idx].id);
    }

    var toolbar = [
      {name: 'document', items: ['Print', 'Templates']},
      {name: 'clipboard', items: ['Cut', 'Copy', 'Paste', '-', 'Undo', 'Redo']},
      {name: 'editing', items: ['Find', 'Replace', '-', 'SelectAll', '-', 'Scayt']},
      {name: 'basicstyles', items: ['Bold', 'Italic', 'Underline', 'Strike', 'Subscript', 'Superscript', '-', 'RemoveFormat']},
      {name: 'paragraph', items: ['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Blockquote', '-', 'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock']},
      {name: 'links', items: ['instructure_links', 'Unlink']},
      {name: 'insert', items: ['Table', 'HorizontalRule', 'Smiley', 'SpecialChar', 'EqnEditor', 'instructure_image']},
      {name: 'styles', items: ['Styles', 'Format', 'Font', 'FontSize']},
      {name: 'colors', items: ['TextColor', 'BGColor']},
      {name: 'tools', items: ['Maximize', 'ShowBlocks']},
      {name: 'others', items: extra_buttons}
    ];

    var ckOptions = $.extend({
      allowedContent: true,
      startupFocus: options.focus,
      toolbar: toolbar,
      pasteFromWordRemoveFontStyles: false,
      pasteFromWordRemoveStyles: false,
      extraPlugins: 'instructure_external_tools,instructure_links,instructure_image',
      removePlugins: 'image',
      removeButtons: '',
      contentsCss: [CKEDITOR.getUrl('contents.css'), '/stylesheets/static/baseline.type.css'],
      on: {
        focus: function(evt) {
          var $editor = $(evt.editor.element);
          $(document).triggerHandler('editor_box_focus', $editor);
          $.publish('editorBox/focus', $editor);
        }
      }
    }, options.tinyOptions || {});

    CKEDITOR.replace($textarea[0], ckOptions);

    this._textarea =  $textarea;
    this._editor = null;
    this._id = id;
    this._searchURL = search_url;
    this._submitURL = submit_url;
    this._contentURL = content_url;
    $instructureEditorBoxList._addEditorBox(id, this);
  }

// --------------------------------------------------------------------

  var editorBoxIdCounter = 1;

  $.fn.editorBox = function(options, more_options) {
    var args = arguments;
    if(this.length > 1) {
      return this.each(function() {
        var $this = $(this);
        $this.editorBox.apply($this, args);
      });
    }

    var id = this.attr('id');
    if(typeof(options) == "string" && options != "create") {
      if(options == "get_code") {
        return this._getContentCode(more_options);
      } else if(options == "set_code") {
        this._setContentCode(more_options);
      } else if(options == "insert_code") {
        this._insertHTML(more_options);
      } else if(options == "create_link") {
        this._linkSelection(more_options);
      } else if(options == "focus") {
        return this._editorFocus(more_options);
      } else if(options == "toggle") {
        this._toggleView();
      } else if(options == "execute") {
        var arr = [];
        for(var idx = 1; idx < arguments.length; idx++) {
          arr.push(arguments[idx]);
        }
        return $.fn._execCommand.apply(this, arr);
      } else if(options == "destroy") {
        this._removeEditor(more_options);
      } else if(options == "is_dirty") {
        return $instructureEditorBoxList._getEditor(id).checkDirty();
      } else if(options == 'exists?') {
        return !!$instructureEditorBoxList._getEditor(id);
      }
      return this;
    }
    this.data('rich_text', true);
    if(!id) {
      id = 'editor_box_unique_id_' + editorBoxIdCounter++;
      this.attr('id', id);
    }
    if($instructureEditorBoxList._getEditor(id)) {
      this._setContentCode(this.val());
      return this;
    }
    var search_url = "";
    if(options && options.search_url) {
      search_url = options.search_url;
    }
    var box = new EditorBox(id, search_url, "", "", options);
    return this;
  };

  $.fn._execCommand = function() {
    var id = $(this).attr('id');
    var editor = $instructureEditorBoxList._getEditor(id);
    if(editor && editor.execCommand) {
      editor.execCommand.apply(editor, arguments);
    }
    return this;
  };

  $.fn._justGetCode = function() {
    var id = this.attr('id') || '';
    var content = '';
    try {
      content = $instructureEditorBoxList._getEditor(id).getData();
    } catch(e) {}
    return content;
  };

  $.fn._getContentCode = function(update) {
    if(update == true) {
      var content = this._justGetCode(); //""
      this._setContentCode(content);
    }
    return this._justGetCode();
  };

  $.fn._getSearchURL = function() {
    return $instructureEditorBoxList._getEditorBox(this.attr('id'))._searchURL;
  };

  $.fn._getSubmitURL = function() {
    return $instructureEditorBoxList._getEditorBox(this.attr('id'))._submitURL;
  };

  $.fn._getContentURL = function() {
    return $instructureEditorBoxList._getEditorBox(this.attr('id'))._contentURL;
  };

  $.fn._toggleView = function() {
    var id = this.attr('id');
    var editor = $instructureEditorBoxList._getEditor(id);
    if (editor) {
      editor.setMode(editor.mode === 'source' ? 'wysiwyg' : 'source');
    }
  };

  $.fn._removeEditor = function() {
    var id = this.attr('id');
    this.data('rich_text', false);
    var editor = $instructureEditorBoxList._getEditor(id);
    if (editor) {
      editor.destroy();
      $instructureEditorBoxList._removeEditorBox(id);
    }
  };

  $.fn._setContentCode = function(val) {
    var id = this.attr('id');
    var editor = $instructureEditorBoxList._getEditor(id);
    if (editor) {
      editor.setData(val, {
        callback: function() {
          $instructureEditorBoxList._getEditor(id).updateElement();
        }
      });
    }
  };

  $.fn._insertHTML = function(html) {
    var id = this.attr('id');
    var editor = $instructureEditorBoxList._getEditor(id);
    if (editor) {
      editor.insertHtml(html, 'unfiltered_html');
    }
  };

  $.fn._editorFocus = function() {
    var $element = this,
        id = $element.attr('id'),
        editor = $instructureEditorBoxList._getEditor(id);
    if(!editor ) {
      return false;
    }
    editor.focus();
    $.publish('editorBox/focus', $element);
    return true;
  };

  $.fn._linkSelection = function(options) {
    if(typeof(options) == "string") {
      options = {url: options};
    }
    var title = options.title;
    var url = options.url || "";
    if(url.match(/@/) && !url.match(/\//) && !url.match(/^mailto:/)) {
      url = "mailto:" + url;
    } else if(!url.match(/^\w+:\/\//) && !url.match(/^mailto:/) && !url.match(/^\//)) {
      url = "http://" + url;
    }
    var classes = options.classes || "";
    var defaultText = options.text || options.title || "Link";
    var target = options.target || null;
    var id = $(this).attr('id');
    if(url.indexOf("@") != -1) {
      options.file = false;
      options.image = false;
      if(url.indexOf("mailto:") != 0) {
        url = "mailto:" + url;
      }
    } else if (url.indexOf("/") == -1) {
      title = url;
      url = url.replace(/\s/g, "");
      url = location.href + url;
    }
    if(options.file) {
      classes += "instructure_file_link ";
    }
    if(options.scribdable) {
      classes += "instructure_scribd_file ";
    }
    var link_id = '';
    if(options.kaltura_entry_id && options.kaltura_media_type) {
      link_id = "media_comment_" + options.kaltura_entry_id;
      if(options.kaltura_media_type == 'video') {
        classes += "instructure_video_link ";
      } else {
        classes += "instructure_audio_link ";
      }
    }
    if(options.image) {
      classes += "instructure_image_thumbnail ";
    }
    classes = $.unique(classes.split(/\s+/)).join(" ");
    var selectionText = "";
    var editor = $instructureEditorBoxList._getEditor(id);
    if(enableBookmarking && this.data('last_bookmark')) {
      editor.getSelection().selectBookmarks(this.data('last_bookmark'));
    }
    var selection = editor.getSelection();
    var anchor = selection.getSelectedElement();
    while(anchor && anchor.getName() != 'A' && anchor.getName() != 'BODY' && anchor.getParent()) {
      anchor = anchor.getParent();
    }
    if(anchor && anchor.getName() != 'A') { anchor = null; }

    var selectedContent = selection.getSelectedText();
    if(!selectedContent || selectedContent == "") {
      if(anchor) {
        $(anchor).attr({
          href: url,
          title: title || '',
          id: link_id,
          'class': classes,
          target: target
        });
      } else {
        selectionText = defaultText;
        var $div = $("<div/>");
        $div.append($("<a/>", {id: link_id, target: target, title: title, href: url, 'class': classes}).text(selectionText));
        editor.insertHtml($div.html(), 'unfiltered_html');
      }
    } else {
      var $div = $("<div/>");
      $div.append($("<a/>", {target: (target || ''), title: (title || ''), href: url, 'class': classes, 'id': link_id}).text(selectedContent));
      editor.insertHtml($div.html(), 'unfiltered_html');
    }
  };

});
<|endoftext|>


<commit_before>MeteorApp = {};

MeteorApp.data = {
    playerId: null
};

MeteorApp.Card = new Mongo.Collection("Card");
MeteorApp.Action = new Mongo.Collection("Action");

MeteorApp.imageFileNames = [
    'adopt',
    'archer',
    'archerfemale',
    'blind',
    'blindfemale',
    'bodyguard',
    'burglar',
    'burglarfemale',
    'citizen',
    'citizenfemale',
    'farmer',
    'hunter',
    'hunterfemale',
    'master_archer',
    'master_archerfemale',
    'master_oracle',
    'medium',
    'mediumfemale',
    'ninja',
    'ninjafemale',
    'oracle',
    'oraclemale',
    'pickpocket',
    'pickpocketfemale',
    'rebel',
    'rogue',
    'roguefemale',
    'runaway',
    'shadow_walker',
    'shadow_walkerfemale',
    'thief',
    'thieffemale',
    'warden',
    'warrior',
    'witch'
];

Meteor.methods({
    moveCard: function(id, position) {
        var card = MeteorApp.Card.findOne({_id: id});
        card.x = position.x;
        card.y = position.y;

        MeteorApp.Card.update(id, card);

        MeteorApp.Action.insert({
            type: 'Backend:cardMoved',
            params: {
                id: id,
                position: position
            }
        });
    },

    removeCard: function(id) {
        MeteorApp.Card.remove(id);

        MeteorApp.Action.insert({
            type: 'Backend:cardRemoved',
            params: {
                id: id
            }
        });
    },

    tapCard: function(id) {
        var card = MeteorApp.Card.findOne({_id: id});
        card.isTapped = true;

        MeteorApp.Card.update(id, card);

        MeteorApp.Action.insert({
            type: 'Backend:cardTapped',
            params: {
                id: id
            }
        });
    },

    untapCard: function(id) {
        var card = MeteorApp.Card.findOne({_id: id});
        card.isTapped = false;

        MeteorApp.Card.update(id, card);

        MeteorApp.Action.insert({
            type: 'Backend:cardUntapped',
            params: {
                id: id
            }
        });
    },

    playAsMana: function(id) {
        var card = MeteorApp.Card.findOne({_id: id});
        if (card.cardGroup == 'hand') {
            card.cardGroup = 'manaPool';
            MeteorApp.Card.update(id, card);

            MeteorApp.Action.insert({
                type: 'Backend:cardPlayedAsMana',
                params: {
                    id: id,
                    ownerId: card.ownerId
                }
            });
        }
    },

    drawCard: function(id) {
        var card = MeteorApp.Card.findOne({_id: id});
        if (card.cardGroup == 'deck') {
            card.cardGroup = 'hand';
            MeteorApp.Card.update(id, card);

            MeteorApp.Action.insert({
                type: 'Backend:cardDrawn',
                params: {
                    id: id,
                    ownerId: card.ownerId
                }
            });
        }
    },

    playCard: function(id, position) {
        var card = MeteorApp.Card.findOne({_id: id});
        card.cardGroup = 'table';
        card.x = position.x;
        card.y = position.y;

        MeteorApp.Card.update(id, card);

        MeteorApp.Action.insert({
            type: 'Backend:cardPlayed',
            params: {
                id: id,
                position: position,
                ownerId: card.ownerId
            }
        });
    },

    moveCardToPreviousGroup: function(id) {
        var card = MeteorApp.Card.findOne({_id: id});
        var group = card.cardGroup;

        if (group === 'table') {
            card.cardGroup = 'hand';
        } else if(group === 'hand') {
            card.cardGroup = 'deck';
        } else if(group === 'graveyard') {
            card.cardGroup = 'table';
        }

        MeteorApp.Card.update(id, card);

        MeteorApp.Action.insert({
            type: 'Backend:cardMovedToPreviousGroup',
            params: {
                id: id,
                oldCardGroup: group,
                newCardGroup: card.cardGroup,
                ownerId: card.ownerId
            }
        });
    },

    addHealth: function(id, health) {
        var card = MeteorApp.Card.findOne({_id: id});
        card.health = card.health + health;

        MeteorApp.Card.update(id, card);

        MeteorApp.Action.insert({
            type: 'Backend:cardHealthChanged',
            params: {
                id: id,
                health: card.health
            }
        });

        if (card.health <= 0 && card.cardGroup == 'table') {
            card.cardGroup = 'graveyard';
            MeteorApp.Card.update(id, card);

            MeteorApp.Action.insert({
                type: 'Backend:cardDied',
                params: {
                    id: id,
                    ownerId: card.ownerId
                }
            });
        }
    },

    addCounter: function(id, counter) {
        var card = MeteorApp.Card.findOne({_id: id});
        card.counter = card.counter + counter;
        if (card.counter < 0 || card.counter > 6) {
            return;
        }

        MeteorApp.Card.update(id, card);

        MeteorApp.Action.insert({
            type: 'Backend:cardCounterChanged',
            params: {
                id: id,
                counter: card.counter
            }
        });
    }
});
<commit_msg>Ctrl+z on mana<commit_after>MeteorApp = {};

MeteorApp.data = {
    playerId: null
};

MeteorApp.Card = new Mongo.Collection("Card");
MeteorApp.Action = new Mongo.Collection("Action");

MeteorApp.imageFileNames = [
    'adopt',
    'archer',
    'archerfemale',
    'blind',
    'blindfemale',
    'bodyguard',
    'burglar',
    'burglarfemale',
    'citizen',
    'citizenfemale',
    'farmer',
    'hunter',
    'hunterfemale',
    'master_archer',
    'master_archerfemale',
    'master_oracle',
    'medium',
    'mediumfemale',
    'ninja',
    'ninjafemale',
    'oracle',
    'oraclemale',
    'pickpocket',
    'pickpocketfemale',
    'rebel',
    'rogue',
    'roguefemale',
    'runaway',
    'shadow_walker',
    'shadow_walkerfemale',
    'thief',
    'thieffemale',
    'warden',
    'warrior',
    'witch'
];

var GroupName = {
    DECK: 'deck',
    HAND: 'hand',
    TABLE: 'table',
    MANA_POOL: 'manaPool',
    GRAVEYARD: 'graveyard'
};

Meteor.methods({
    moveCard: function(id, position) {
        var card = MeteorApp.Card.findOne({_id: id});
        card.x = position.x;
        card.y = position.y;

        MeteorApp.Card.update(id, card);

        MeteorApp.Action.insert({
            type: 'Backend:cardMoved',
            params: {
                id: id,
                position: position
            }
        });
    },

    removeCard: function(id) {
        MeteorApp.Card.remove(id);

        MeteorApp.Action.insert({
            type: 'Backend:cardRemoved',
            params: {
                id: id
            }
        });
    },

    tapCard: function(id) {
        var card = MeteorApp.Card.findOne({_id: id});
        card.isTapped = true;

        MeteorApp.Card.update(id, card);

        MeteorApp.Action.insert({
            type: 'Backend:cardTapped',
            params: {
                id: id
            }
        });
    },

    untapCard: function(id) {
        var card = MeteorApp.Card.findOne({_id: id});
        card.isTapped = false;

        MeteorApp.Card.update(id, card);

        MeteorApp.Action.insert({
            type: 'Backend:cardUntapped',
            params: {
                id: id
            }
        });
    },

    playAsMana: function(id) {
        var card = MeteorApp.Card.findOne({_id: id});
        if (card.cardGroup == GroupName.HAND) {
            card.cardGroup = GroupName.MANA_POOL;
            MeteorApp.Card.update(id, card);

            MeteorApp.Action.insert({
                type: 'Backend:cardPlayedAsMana',
                params: {
                    id: id,
                    ownerId: card.ownerId
                }
            });

            MeteorApp.Action.insert({
                type: 'Backend:cardTapped',
                params: {
                    id: id
                }
            });
        }
    },

    drawCard: function(id) {
        var card = MeteorApp.Card.findOne({_id: id});
        if (card.cardGroup == GroupName.DECK) {
            card.cardGroup = GroupName.HAND;
            MeteorApp.Card.update(id, card);

            MeteorApp.Action.insert({
                type: 'Backend:cardDrawn',
                params: {
                    id: id,
                    ownerId: card.ownerId
                }
            });
        }
    },

    playCard: function(id, position) {
        var card = MeteorApp.Card.findOne({_id: id});
        card.cardGroup = GroupName.TABLE;
        card.x = position.x;
        card.y = position.y;

        MeteorApp.Card.update(id, card);

        MeteorApp.Action.insert({
            type: 'Backend:cardPlayed',
            params: {
                id: id,
                position: position,
                ownerId: card.ownerId
            }
        });
    },

    moveCardToPreviousGroup: function(id) {
        var card = MeteorApp.Card.findOne({_id: id});
        var group = card.cardGroup;

        if (group === GroupName.TABLE) {
            card.cardGroup = GroupName.HAND;
        } else if(group === GroupName.HAND) {
            card.cardGroup = GroupName.DECK;
        } else if(group === GroupName.GRAVEYARD) {
            card.cardGroup = GroupName.TABLE;
        } else if(group === GroupName.MANA_POOL) {
            card.cardGroup = GroupName.HAND;
        }

        MeteorApp.Card.update(id, card);

        MeteorApp.Action.insert({
            type: 'Backend:cardMovedToPreviousGroup',
            params: {
                id: id,
                oldCardGroup: group,
                newCardGroup: card.cardGroup,
                ownerId: card.ownerId
            }
        });
    },

    addHealth: function(id, health) {
        var card = MeteorApp.Card.findOne({_id: id});
        card.health = card.health + health;

        MeteorApp.Card.update(id, card);

        MeteorApp.Action.insert({
            type: 'Backend:cardHealthChanged',
            params: {
                id: id,
                health: card.health
            }
        });

        if (card.health <= 0 && card.cardGroup == GroupName.TABLE) {
            card.cardGroup = GroupName.GRAVEYARD;
            MeteorApp.Card.update(id, card);

            MeteorApp.Action.insert({
                type: 'Backend:cardDied',
                params: {
                    id: id,
                    ownerId: card.ownerId
                }
            });
        }
    },

    addCounter: function(id, counter) {
        var card = MeteorApp.Card.findOne({_id: id});
        card.counter = card.counter + counter;
        if (card.counter < 0 || card.counter > 6) {
            return;
        }

        MeteorApp.Card.update(id, card);

        MeteorApp.Action.insert({
            type: 'Backend:cardCounterChanged',
            params: {
                id: id,
                counter: card.counter
            }
        });
    }
});
<|endoftext|>


<commit_before>/**
 * @license Copyright (c) CKSource - Frederico Knabben. All rights reserved.
 * For licensing, see LICENSE.html or http://ckeditor.com/license
 */

(function() {
    if (!supportsLocalStorage()) {
        CKEDITOR.plugins.add("autosave", {}); //register a dummy plugin to pass CKEditor plugin initialization process
        return;
    }

    CKEDITOR.plugins.add("autosave", {
        lang: 'ca,cs,de,en,es,fr,ja,pl,pt-br,ru,sv,zh,zh-cn', // %REMOVE_LINE_CORE%
        requires: 'notification',
        version: 0.13,
        init: function(editor) {
            CKEDITOR.document.appendStyleSheet(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'css/autosave.min.css'));

            editor.on('instanceReady', function(){
                if (typeof (jQuery) === 'undefined') {
                    CKEDITOR.scriptLoader.load('//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js', function() {
                        jQuery.noConflict();

                        loadPlugin(editor);
                    });

                } else {
                    CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'js/extensions.min.js'), function() {
                        loadPlugin(editor);
                    });
                }
            }, editor, null, 100);
        }
    });

    function loadPlugin(editorInstance) {
        var autoSaveKey = editorInstance.config.autosave_SaveKey != null ? editorInstance.config.autosave_SaveKey : 'autosave_' + window.location + "_" + editorInstance.id;
        var notOlderThen = editorInstance.config.autosave_NotOlderThen != null ? editorInstance.config.autosave_NotOlderThen : 1440;
        var saveOnDestroy = editorInstance.config.autosave_saveOnDestroy != null ? editorInstance.config.autosave_saveOnDestroy : false;
        var saveDetectionSelectors =
            editorInstance.config.autosave_saveDetectionSelectors != null ? editorInstance.config.autosave_saveDetectionSelectors : "a[href^='javascript:__doPostBack'][id*='Save'],a[id*='Cancel']";

        CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'js/extensions.min.js'), function() {
            GenerateAutoSaveDialog(editorInstance, autoSaveKey);

            CheckForAutoSavedContent(editorInstance, autoSaveKey, notOlderThen);
        });

        jQuery(saveDetectionSelectors).click(function() {
            RemoveStorage(autoSaveKey);
        });

        editorInstance.on('change', startTimer);

        editorInstance.on('destroy', function() {
            if (saveOnDestroy) {
                SaveData(autoSaveKey, editorInstance);
            }
        });
    }

    var timeOutId = 0,
        savingActive = false;

    var startTimer = function(event) {
        if (timeOutId) {
        } else {
            var delay = event.editor.config.autosave_delay != null ? event.editor.config.autosave_delay : 10;
            timeOutId = setTimeout(onTimer, delay * 1000, event);
        }

    };
    var onTimer = function(event) {
        if (savingActive) {
            startTimer(event);
        } else if (event.editor.checkDirty() || event.editor.plugins.bbcode) {
            savingActive = true;
            var editor = event.editor,
                autoSaveKey = editor.config.autosave_SaveKey != null ? editor.config.autosave_SaveKey : 'autosave_' + window.location + "_" + editor.id;

            SaveData(autoSaveKey, editor);

            timeOutId = 0;
            savingActive = false;
        }
    };

    // localStorage detection
    function supportsLocalStorage() {
        if (typeof (Storage) === 'undefined') {
            return false;
        }

        try {
            localStorage.getItem("___test_key");
            return true;
        } catch (e) {
            return false;
        }
    }

    function GenerateAutoSaveDialog(editorInstance, autoSaveKey) {
        CKEDITOR.dialog.add('autosaveDialog', function() {
            return {
                title: editorInstance.lang.autosave.title,
                minHeight: 155,
                height: 300,
                width: 750,
                onShow: function() {
                    RenderDiff(this, editorInstance, autoSaveKey);
                },
                onOk: function() {
                    if (localStorage.getItem(autoSaveKey)) {
                        var jsonSavedContent = LoadData(autoSaveKey);
                        editorInstance.loadSnapshot(jsonSavedContent.data);

                        RemoveStorage(autoSaveKey);
                    }
                },
                onCancel: function() {
                    RemoveStorage(autoSaveKey);
                },
                contents: [
                    {
                        label: '',
                        id: 'general',
                        elements: [
                            {
                                type: 'radio',
                                id: 'diffType',
                                label: editorInstance.lang.autosave.diffType,
                                items: [[editorInstance.lang.autosave.sideBySide, 'sideBySide'], [editorInstance.lang.autosave.inline, 'inline']],
                                'default': 'sideBySide',
                                onClick: function() {
                                    RenderDiff(this._.dialog, editorInstance, autoSaveKey);
                                }
                            }, {
                                type: 'html',
                                id: 'diffContent',
                                html: ''
                            }
                        ]
                    }
                ],
                buttons: [
                    {
                        id: 'ok',
                        type: 'button',
                        label: editorInstance.lang.autosave.ok,
                        'class': 'cke_dialog_ui_button_ok cke_dialog_autosave_ok',
                        onClick: function(evt) {
                            var dialog = evt.data.dialog;
                            if (dialog.fire('ok', { hide: true }).hide !== false)
                                dialog.hide();
                        }
                    },
                    {
                        id: 'cancel',
                        type: 'button',
                        label: editorInstance.lang.autosave.no,
                        'class': 'cke_dialog_ui_button_cancel',
                        onClick: function(evt) {
                            var dialog = evt.data.dialog;
                            if (dialog.fire('cancel', { hide: true }).hide !== false)
                                dialog.hide();
                        }
                    }
                ]
            };
        });
    }

    function CheckForAutoSavedContent(editorInstance, autoSaveKey, notOlderThen) {
        // Checks If there is data available and load it
        if (localStorage.getItem(autoSaveKey)) {
            var jsonSavedContent = LoadData(autoSaveKey);

            var autoSavedContent = jsonSavedContent.data;
            var autoSavedContentDate = jsonSavedContent.saveTime;

            var editorLoadedContent = editorInstance.getSnapshot();

            // check if the loaded editor content is the same as the autosaved content
            if (editorLoadedContent == autoSavedContent) {
                localStorage.removeItem(autoSaveKey);
                return;
            }

            // Ignore if autosaved content is older then x minutes
            if (moment(new Date()).diff(new Date(autoSavedContentDate), 'minutes') > notOlderThen) {
                RemoveStorage(autoSaveKey);

                return;
            }

            var confirmMessage = editorInstance.lang.autosave.loadSavedContent.replace("{0}", moment(autoSavedContentDate).locale(editorInstance.config.language).format(editorInstance.lang.autosave.dateFormat));
            if (confirm(confirmMessage)) {
                // Open DIFF Dialog
                editorInstance.openDialog('autosaveDialog');
            } else {
                RemoveStorage(autoSaveKey);
            }
        }
    }

    function LoadData(autoSaveKey) {
        var compressedJSON = LZString.decompressFromUTF16(localStorage.getItem(autoSaveKey));
        return JSON.parse(compressedJSON);
    }

    function SaveData(autoSaveKey, editorInstance) {
        var compressedJSON = LZString.compressToUTF16(JSON.stringify({ data: editorInstance.getSnapshot(), saveTime: new Date() }));
        localStorage.setItem(autoSaveKey, compressedJSON);

        if (typeof editorInstance.config.autosave_disableNotifications === "undefined" || !editorInstance.config.autosave_disableNotifications) {
            var notification = new CKEDITOR.plugins.notification(editorInstance, { message: editorInstance.lang.autosave.autoSaveMessage, type: 'success' });
            notification.show();
        }
    }

    function RemoveStorage(autoSaveKey) {
        if (timeOutId) {
            clearTimeout(timeOutId);
        }

        localStorage.removeItem(autoSaveKey);
    }

    function RenderDiff(dialog, editorInstance, autoSaveKey) {
        var jsonSavedContent = LoadData(autoSaveKey);

        var base = difflib.stringAsLines(editorInstance.getSnapshot());
        var newtxt = difflib.stringAsLines(jsonSavedContent.data);
        var sm = new difflib.SequenceMatcher(base, newtxt);
        var opcodes = sm.get_opcodes();

        dialog.getContentElement('general', 'diffContent').getElement().setHtml('
' + diffview.buildView({
            baseTextLines: base,
            newTextLines: newtxt,
            opcodes: opcodes,
            baseTextName: editorInstance.lang.autosave.loadedContent,
            newTextName: editorInstance.lang.autosave.autoSavedContent + (moment(jsonSavedContent.saveTime).locale(editorInstance.config.language).format(editorInstance.lang.autosave.dateFormat)) + '\'',
            contextSize: 3,
            viewType: dialog.getContentElement('general', 'diffType').getValue() == "inline" ? 1 : 0
        }).outerHTML + '
');
    }
})();
<commit_msg>enabled dutch language<commit_after>/**
 * @license Copyright (c) CKSource - Frederico Knabben. All rights reserved.
 * For licensing, see LICENSE.html or http://ckeditor.com/license
 */

(function() {
    if (!supportsLocalStorage()) {
        CKEDITOR.plugins.add("autosave", {}); //register a dummy plugin to pass CKEditor plugin initialization process
        return;
    }

    CKEDITOR.plugins.add("autosave", {
        lang: 'ca,cs,de,en,es,fr,ja,nl,pl,pt-br,ru,sv,zh,zh-cn', // %REMOVE_LINE_CORE%
        requires: 'notification',
        version: 0.13,
        init: function(editor) {
            CKEDITOR.document.appendStyleSheet(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'css/autosave.min.css'));

            editor.on('instanceReady', function(){
                if (typeof (jQuery) === 'undefined') {
                    CKEDITOR.scriptLoader.load('//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js', function() {
                        jQuery.noConflict();

                        loadPlugin(editor);
                    });

                } else {
                    CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'js/extensions.min.js'), function() {
                        loadPlugin(editor);
                    });
                }
            }, editor, null, 100);
        }
    });

    function loadPlugin(editorInstance) {
        var autoSaveKey = editorInstance.config.autosave_SaveKey != null ? editorInstance.config.autosave_SaveKey : 'autosave_' + window.location + "_" + editorInstance.id;
        var notOlderThen = editorInstance.config.autosave_NotOlderThen != null ? editorInstance.config.autosave_NotOlderThen : 1440;
        var saveOnDestroy = editorInstance.config.autosave_saveOnDestroy != null ? editorInstance.config.autosave_saveOnDestroy : false;
        var saveDetectionSelectors =
            editorInstance.config.autosave_saveDetectionSelectors != null ? editorInstance.config.autosave_saveDetectionSelectors : "a[href^='javascript:__doPostBack'][id*='Save'],a[id*='Cancel']";

        CKEDITOR.scriptLoader.load(CKEDITOR.getUrl(CKEDITOR.plugins.getPath('autosave') + 'js/extensions.min.js'), function() {
            GenerateAutoSaveDialog(editorInstance, autoSaveKey);

            CheckForAutoSavedContent(editorInstance, autoSaveKey, notOlderThen);
        });

        jQuery(saveDetectionSelectors).click(function() {
            RemoveStorage(autoSaveKey);
        });

        editorInstance.on('change', startTimer);

        editorInstance.on('destroy', function() {
            if (saveOnDestroy) {
                SaveData(autoSaveKey, editorInstance);
            }
        });
    }

    var timeOutId = 0,
        savingActive = false;

    var startTimer = function(event) {
        if (timeOutId) {
        } else {
            var delay = event.editor.config.autosave_delay != null ? event.editor.config.autosave_delay : 10;
            timeOutId = setTimeout(onTimer, delay * 1000, event);
        }

    };
    var onTimer = function(event) {
        if (savingActive) {
            startTimer(event);
        } else if (event.editor.checkDirty() || event.editor.plugins.bbcode) {
            savingActive = true;
            var editor = event.editor,
                autoSaveKey = editor.config.autosave_SaveKey != null ? editor.config.autosave_SaveKey : 'autosave_' + window.location + "_" + editor.id;

            SaveData(autoSaveKey, editor);

            timeOutId = 0;
            savingActive = false;
        }
    };

    // localStorage detection
    function supportsLocalStorage() {
        if (typeof (Storage) === 'undefined') {
            return false;
        }

        try {
            localStorage.getItem("___test_key");
            return true;
        } catch (e) {
            return false;
        }
    }

    function GenerateAutoSaveDialog(editorInstance, autoSaveKey) {
        CKEDITOR.dialog.add('autosaveDialog', function() {
            return {
                title: editorInstance.lang.autosave.title,
                minHeight: 155,
                height: 300,
                width: 800,
                onShow: function() {
                    RenderDiff(this, editorInstance, autoSaveKey);
                },
                onOk: function() {
                    if (localStorage.getItem(autoSaveKey)) {
                        var jsonSavedContent = LoadData(autoSaveKey);
                        editorInstance.loadSnapshot(jsonSavedContent.data);

                        RemoveStorage(autoSaveKey);
                    }
                },
                onCancel: function() {
                    RemoveStorage(autoSaveKey);
                },
                contents: [
                    {
                        label: '',
                        id: 'general',
                        elements: [
                            {
                                type: 'radio',
                                id: 'diffType',
                                label: editorInstance.lang.autosave.diffType,
                                items: [[editorInstance.lang.autosave.sideBySide, 'sideBySide'], [editorInstance.lang.autosave.inline, 'inline']],
                                'default': 'sideBySide',
                                onClick: function() {
                                    RenderDiff(this._.dialog, editorInstance, autoSaveKey);
                                }
                            }, {
                                type: 'html',
                                id: 'diffContent',
                                html: ''
                            }
                        ]
                    }
                ],
                buttons: [
                    {
                        id: 'ok',
                        type: 'button',
                        label: editorInstance.lang.autosave.ok,
                        'class': 'cke_dialog_ui_button_ok cke_dialog_autosave_ok',
                        onClick: function(evt) {
                            var dialog = evt.data.dialog;
                            if (dialog.fire('ok', { hide: true }).hide !== false)
                                dialog.hide();
                        }
                    },
                    {
                        id: 'cancel',
                        type: 'button',
                        label: editorInstance.lang.autosave.no,
                        'class': 'cke_dialog_ui_button_cancel',
                        onClick: function(evt) {
                            var dialog = evt.data.dialog;
                            if (dialog.fire('cancel', { hide: true }).hide !== false)
                                dialog.hide();
                        }
                    }
                ]
            };
        });
    }

    function CheckForAutoSavedContent(editorInstance, autoSaveKey, notOlderThen) {
        // Checks If there is data available and load it
        if (localStorage.getItem(autoSaveKey)) {
            var jsonSavedContent = LoadData(autoSaveKey);

            var autoSavedContent = jsonSavedContent.data;
            var autoSavedContentDate = jsonSavedContent.saveTime;

            var editorLoadedContent = editorInstance.getSnapshot();

            // check if the loaded editor content is the same as the autosaved content
            if (editorLoadedContent == autoSavedContent) {
                localStorage.removeItem(autoSaveKey);
                return;
            }

            // Ignore if autosaved content is older then x minutes
            if (moment(new Date()).diff(new Date(autoSavedContentDate), 'minutes') > notOlderThen) {
                RemoveStorage(autoSaveKey);

                return;
            }

            var confirmMessage = editorInstance.lang.autosave.loadSavedContent.replace("{0}", moment(autoSavedContentDate).locale(editorInstance.config.language).format(editorInstance.lang.autosave.dateFormat));
            if (confirm(confirmMessage)) {
                // Open DIFF Dialog
                editorInstance.openDialog('autosaveDialog');
            } else {
                RemoveStorage(autoSaveKey);
            }
        }
    }

    function LoadData(autoSaveKey) {
        var compressedJSON = LZString.decompressFromUTF16(localStorage.getItem(autoSaveKey));
        return JSON.parse(compressedJSON);
    }

    function SaveData(autoSaveKey, editorInstance) {
        var compressedJSON = LZString.compressToUTF16(JSON.stringify({ data: editorInstance.getSnapshot(), saveTime: new Date() }));
        localStorage.setItem(autoSaveKey, compressedJSON);

        if (typeof editorInstance.config.autosave_disableNotifications === "undefined" || !editorInstance.config.autosave_disableNotifications) {
            var notification = new CKEDITOR.plugins.notification(editorInstance, { message: editorInstance.lang.autosave.autoSaveMessage, type: 'success' });
            notification.show();
        }
    }

    function RemoveStorage(autoSaveKey) {
        if (timeOutId) {
            clearTimeout(timeOutId);
        }

        localStorage.removeItem(autoSaveKey);
    }

    function RenderDiff(dialog, editorInstance, autoSaveKey) {
        var jsonSavedContent = LoadData(autoSaveKey);

        var base = difflib.stringAsLines(editorInstance.getSnapshot());
        var newtxt = difflib.stringAsLines(jsonSavedContent.data);
        var sm = new difflib.SequenceMatcher(base, newtxt);
        var opcodes = sm.get_opcodes();

        dialog.getContentElement('general', 'diffContent').getElement().setHtml('
' + diffview.buildView({
            baseTextLines: base,
            newTextLines: newtxt,
            opcodes: opcodes,
            baseTextName: editorInstance.lang.autosave.loadedContent,
            newTextName: editorInstance.lang.autosave.autoSavedContent + (moment(jsonSavedContent.saveTime).locale(editorInstance.config.language).format(editorInstance.lang.autosave.dateFormat)) + '\'',
            contextSize: 3,
            viewType: dialog.getContentElement('general', 'diffType').getValue() == "inline" ? 1 : 0
        }).outerHTML + '
');
    }
})();
<|endoftext|>


<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var Tapable = require("tapable");
var async = require("async");
var Stats = require("./Stats");

function MultiWatching(watchings) {
	this.watchings = watchings;
}

MultiWatching.prototype.invalidate = function() {
	this.watchings.forEach(function(watching) {
		watching.invalidate();
	});
};

MultiWatching.prototype.close = function(callback) {
	async.forEach(this.watchings, function(watching, callback) {
		watching.close(callback);
	}, callback);
};

function MultiCompiler(compilers) {
	Tapable.call(this);
	if(!Array.isArray(compilers)) {
		compilers = Object.keys(compilers).map(function(name) {
			compilers[name].name = name;
			return compilers[name];
		});
	}
	this.compilers = compilers;

	function delegateProperty(name) {
		Object.defineProperty(this, name, {
			configurable: false,
			get: function() {
				throw new Error("Cannot read " + name + " of a MultiCompiler");
			},
			set: function(value) {
				this.compilers.forEach(function(compiler) {
					compiler[name] = value;
				});
			}.bind(this)
		});
	}
	delegateProperty.call(this, "outputFileSystem");
	delegateProperty.call(this, "inputFileSystem");

	var doneCompilers = 0;
	var compilerStats = [];
	this.compilers.forEach(function(compiler, idx) {
		var compilerDone = false;
		compiler.plugin("done", function(stats) {
			if(!compilerDone) {
				compilerDone = true;
				doneCompilers++;
			}
			compilerStats[idx] = stats;
			if(doneCompilers === this.compilers.length) {
				this.applyPlugins("done", new MultiStats(compilerStats));
			}
		}.bind(this));
		compiler.plugin("invalid", function() {
			this.applyPlugins("invalid");
		});
	}, this);
}
module.exports = MultiCompiler;

MultiCompiler.prototype = Object.create(Tapable.prototype);

MultiCompiler.prototype.watch = function(watchDelay, handler) {
	var watchings = this.compilers.map(function(compiler) {
		return compiler.watch(watchDelay, handler);
	});
	return new MultiWatching(watchings);
};

MultiCompiler.prototype.run = function(callback) {
	async.map(this.compilers, function(compiler, callback) {
		compiler.run(callback);
	}, function(err, stats) {
		if(err) return callback(err);
		callback(null, new MultiStats(stats));
	});
};

MultiCompiler.prototype.purgeInputFileSystem = function() {
	this.compilers.forEach(function(compiler) {
		if(compiler.inputFileSystem && compiler.inputFileSystem.purge)
			compiler.inputFileSystem.purge();
	});
};

function MultiStats(stats) {
	this.stats = stats;
	this.hash = stats.map(function(stat) {
		return stat.hash;
	}).join("");
}

MultiStats.prototype.hasErrors = function() {
	return this.stats.map(function(stat) {
		return stat.hasErrors();
	}).reduce(function(a, b) { return a || b; }, false);
};

MultiStats.prototype.hasWarnings = function() {
	return this.stats.map(function(stat) {
		return stat.hasWarnings();
	}).reduce(function(a, b) { return a || b; }, false);
};

MultiStats.prototype.toJson = function(options, forToString) {
	var jsons = this.stats.map(function(stat) {
		var obj = stat.toJson(options, forToString);
		obj.name = stat.compilation && stat.compilation.name;
		return obj;
	});
	return {
		version: require("../package.json").version,
		hash: this.hash,
		errors: jsons.reduce(function(arr, j) {
			return arr.concat(j.errors.map(function(msg) {
				return "(" + j.name + ") " + msg
			}));
		}, []),
		warnings: jsons.reduce(function(arr, j) {
			return arr.concat(j.warnings.map(function(msg) {
				return "(" + j.name + ") " + msg
			}));
		}, []),
		children: jsons
	};
};

MultiStats.prototype.toString = Stats.prototype.toString;<commit_msg>fixed MultiCompiler with watching<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var Tapable = require("tapable");
var async = require("async");
var Stats = require("./Stats");

function MultiWatching(watchings) {
	this.watchings = watchings;
}

MultiWatching.prototype.invalidate = function() {
	this.watchings.forEach(function(watching) {
		watching.invalidate();
	});
};

MultiWatching.prototype.close = function(callback) {
	async.forEach(this.watchings, function(watching, callback) {
		watching.close(callback);
	}, callback);
};

function MultiCompiler(compilers) {
	Tapable.call(this);
	if(!Array.isArray(compilers)) {
		compilers = Object.keys(compilers).map(function(name) {
			compilers[name].name = name;
			return compilers[name];
		});
	}
	this.compilers = compilers;

	function delegateProperty(name) {
		Object.defineProperty(this, name, {
			configurable: false,
			get: function() {
				throw new Error("Cannot read " + name + " of a MultiCompiler");
			},
			set: function(value) {
				this.compilers.forEach(function(compiler) {
					compiler[name] = value;
				});
			}.bind(this)
		});
	}
	delegateProperty.call(this, "outputFileSystem");
	delegateProperty.call(this, "inputFileSystem");

	var doneCompilers = 0;
	var compilerStats = [];
	this.compilers.forEach(function(compiler, idx) {
		var compilerDone = false;
		compiler.plugin("done", function(stats) {
			if(!compilerDone) {
				compilerDone = true;
				doneCompilers++;
			}
			compilerStats[idx] = stats;
			if(doneCompilers === this.compilers.length) {
				this.applyPlugins("done", new MultiStats(compilerStats));
			}
		}.bind(this));
		compiler.plugin("invalid", function() {
			if(compilerDone) {
				compilerDone = false;
				doneCompilers--;
			}
			this.applyPlugins("invalid");
		}.bind(this));
	}, this);
}
module.exports = MultiCompiler;

MultiCompiler.prototype = Object.create(Tapable.prototype);

MultiCompiler.prototype.watch = function(watchDelay, handler) {
	var watchings = this.compilers.map(function(compiler) {
		return compiler.watch(watchDelay, handler);
	});
	return new MultiWatching(watchings);
};

MultiCompiler.prototype.run = function(callback) {
	async.map(this.compilers, function(compiler, callback) {
		compiler.run(callback);
	}, function(err, stats) {
		if(err) return callback(err);
		callback(null, new MultiStats(stats));
	});
};

MultiCompiler.prototype.purgeInputFileSystem = function() {
	this.compilers.forEach(function(compiler) {
		if(compiler.inputFileSystem && compiler.inputFileSystem.purge)
			compiler.inputFileSystem.purge();
	});
};

function MultiStats(stats) {
	this.stats = stats;
	this.hash = stats.map(function(stat) {
		return stat.hash;
	}).join("");
}

MultiStats.prototype.hasErrors = function() {
	return this.stats.map(function(stat) {
		return stat.hasErrors();
	}).reduce(function(a, b) { return a || b; }, false);
};

MultiStats.prototype.hasWarnings = function() {
	return this.stats.map(function(stat) {
		return stat.hasWarnings();
	}).reduce(function(a, b) { return a || b; }, false);
};

MultiStats.prototype.toJson = function(options, forToString) {
	var jsons = this.stats.map(function(stat) {
		var obj = stat.toJson(options, forToString);
		obj.name = stat.compilation && stat.compilation.name;
		return obj;
	});
	return {
		version: require("../package.json").version,
		hash: this.hash,
		errors: jsons.reduce(function(arr, j) {
			return arr.concat(j.errors.map(function(msg) {
				return "(" + j.name + ") " + msg
			}));
		}, []),
		warnings: jsons.reduce(function(arr, j) {
			return arr.concat(j.warnings.map(function(msg) {
				return "(" + j.name + ") " + msg
			}));
		}, []),
		children: jsons
	};
};

MultiStats.prototype.toString = Stats.prototype.toString;<|endoftext|>


<commit_before>define(
	['view/RenderedView', 'util/Util', 'data/Link', 'view/UserList', 'view/UserManagementPanel', 'text!tmpl/UserManagement.html'],
	function (RenderedView, Util, Link, UserList, UserManagementPanel, tmpl) {
		function validateEmail(email) {
		    var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
		    return re.test(email);
		}

		var This = RenderedView.extend({
			template: _.template( tmpl ),

			initialize: function(opt) {
				this.access = opt.access;
				Link.getAllUsers().asap($.proxy(this.refresh,this));
			},

			refresh : function() {
				this.render();

				if (!Util.permits(this.access,"CREATE_USERS")) {
					$(".add",this.el).hide();
				}

				this.users = Link.getAllUsers().getData();
				this.userList = Util.createView( $(".userlist",this.el), UserList, {users:this.users, decorator: this.userDecorator});
				this.userPanel = Util.createView( $(".management",this.el), UserManagementPanel);

				$(this.userList).on("UserSelected",$.proxy(this.userSelected,this));

				$(".add",this.el).click($.proxy(this.createUserClicked,this));
			},

			userDecorator : function(event,user,$el) {
				if (user.lastActive) {
					console.log(user.email);
					var timeSince = serverTime-moment(user.lastActive).unix();
					var text = "";
					if (timeSince < 1500) text = "online";
					var $decoration = $("");
					$decoration.text(text);
					$el.append($decoration);
				}
				//if (user.lastActive && moment(user.lastActive) )
			},

			userSelected : function(e,userId,user) {
				this.userPanel.setUser(user);
			},

			createUserClicked : function(e) {
				var email = prompt("Enter the email address of the new user:");
				if (!validateEmail(email)) {
					alert("Invalid email address!");
					return;
				}

				Link.createUser({email:email}).post(function(password) {
					alert("The user has been sent an email with instructions on how to activate their account.");
					Link.getAllUsers().pull();
				});
			}
		});

		$.extend(This,{
		});

		return This;
	}
)

<commit_msg>test commit<commit_after>define(
	['view/RenderedView', 'util/Util', 'data/Link', 'view/UserList', 'view/UserManagementPanel', 'text!tmpl/UserManagement.html'],
	function (RenderedView, Util, Link, UserList, UserManagementPanel, tmpl) {
		function validateEmail(email) {
		    var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
		    return re.test(email);
		}

		var This = RenderedView.extend({
			template: _.template( tmpl ),

			initialize: function(opt) {
				this.access = opt.access;
				Link.getAllUsers().asap($.proxy(this.refresh,this));
			},

			refresh : function() {
				this.render();

				if (!Util.permits(this.access,"CREATE_USERS")) {
					$(".add",this.el).hide();
				}

				this.users = Link.getAllUsers().getData();
				this.userList = Util.createView( $(".userlist",this.el), UserList, {users:this.users, decorator: this.userDecorator});
				this.userPanel = Util.createView( $(".management",this.el), UserManagementPanel);

				$(this.userList).on("UserSelected",$.proxy(this.userSelected,this));

				$(".add",this.el).click($.proxy(this.createUserClicked,this));
			},

			userDecorator : function(event,user,$el) {
				if (user.lastActive) {
					console.log(serverTime,moment(user.lastActive).unix(),serverTime-moment(user.lastActive).unix());
					var timeSince = serverTime-moment(user.lastActive).unix();
					var text = "";
					if (timeSince < 1500) text = "online";
					var $decoration = $("");
					$decoration.text(text);
					$el.append($decoration);
				}
				//if (user.lastActive && moment(user.lastActive) )
			},

			userSelected : function(e,userId,user) {
				this.userPanel.setUser(user);
			},

			createUserClicked : function(e) {
				var email = prompt("Enter the email address of the new user:");
				if (!validateEmail(email)) {
					alert("Invalid email address!");
					return;
				}

				Link.createUser({email:email}).post(function(password) {
					alert("The user has been sent an email with instructions on how to activate their account.");
					Link.getAllUsers().pull();
				});
			}
		});

		$.extend(This,{
		});

		return This;
	}
)

<|endoftext|>


<commit_before>// Encryption module. Loaded in window.onload()
// When page is loaded : Encryption.checkAPI();
var Encryption = (function() {
	// Private
	var chunkSize = 1024 * 1024; // Size of one chunk in B
	var CEK = 'password'; // for tests
	var target = 'User';
	var est = 33.5; // Estimation of the difference between the file and encrypted file in %

	var errorHandler = function(e) {
		console.log("Error");
		console.log(e);
	};

	var time;

	// Constructor
	function Encryption(f, f_id, i, reload) {
		var me = this;

		if(reload === true)
			this.reload = true;
		else
			this.reload = false;

		this.folder_id = f_id;
		this.file = f;	// file.name, file.size
		this.est_size = Math.round(f.size*(1+est/100)); // Estimation of encrypted file size
		this.i = i; // Id of file, used only for displaying progress, different from database !
		this.j = 0; // Number of chunks read
		this.k = 0; // Number of chunks written
		this.l = 0; // Number of B written
		this.halt = false;

		this.aDATA = sjcl.random.randomWords(1);
		this.SALT = sjcl.random.randomWords(2);
		this.key = sjcl.misc.pbkdf2(CEK, this.SALT, 2000, 256);
		this.enc = new sjcl.cipher.aes(this.key);

		// Check status before uploading
		var xhr = new XMLHttpRequest();
		xhr.open("POST", target+'/getFileStatus', true);
		xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

		xhr.onreadystatechange = function() {
			// TODO : improve alert (only one) and confirm (yes, no, yes for all, no for all)
			if(xhr.status == 200 && xhr.readyState == 4) {
				if(xhr.responseText == '0') // File doesn't exist, it's ok
					me.read();
				else if(xhr.responseText == '1' || xhr.responseText == '2') // File exists
					if(confirm('The file '+f.name+' exists, do you want to replace it ?'))
						console.log('replace it'); //me.read(); // TODO
				else if(xhr.responseText == 'quota')
					alert('Quota exceeded !');
				else
					alert('Error');
			}
		}
		xhr.send("filename="+f.name+"&filesize="+f.size+"&folder_id="+f_id);
	}

	// Public
	Encryption.prototype.checkAPI = function() {
		if(window.File && window.FileReader && window.FileList && window.Blob) {
			reader = new FileReader();
			return true;
		}
		else {
			alert('The File APIs are not fully supported by your browser. Fallback required.');
			return false;
		}
	};

	Encryption.prototype.toBitArrayCodec = function(bytes) {
		/** Convert from an array of bytes to a bitArray. */
		var out = [], i, tmp=0;
		for (i=0; i<bytes.length; i++) {
			tmp = tmp << 8 | bytes[i];
			if ((i&3) === 3) {
				out.push(tmp);
				tmp = 0;
			}
		}
		if (i&3)
			out.push(sjcl.bitArray.partial(8*(i&3), tmp));
		return out;
	};

	Encryption.prototype.read = function() {
		var me = this;

		time = new Time();
		console.log('File size : '+this.file.size);
		console.log('File name : '+this.file.name);

		this.parseFile(this.file, {
			binary: true,
			chunk_size: chunkSize,
			success: function(i) {
				if(me.halt)
					return false;
				// Waiting end of the uploading process
				var timer = setInterval(function() {
					console.log("Waiting...");
					if(me.k >= me.j) {
						// Done, write "EOF" at the end of file
						clearInterval(timer);

						var xhr = new XMLHttpRequest();
						xhr.open("POST", target+'/writeChunk', true);
						xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

						xhr.onreadystatechange = function() {
							if(xhr.status == 200 && xhr.readyState == 4) {
								time.stop();//
								var node = document.querySelector("#div_upload"+(me.i));
								while(node.firstChild) // remove all children
									node.removeChild(node.firstChild);
								console.log("Split + encryption : "+time.elapsed()+" ms");//
								console.log("Splitted in "+me.j+" chunks !");
								if(me.reload)
									Folders.open(me.folder_id);
							}
						}
						xhr.send("filename="+me.file.name+"&data=EOF&folder_id="+me.folder_id);
					}
				}, 1000);
			},
			chunk_read_callback: function(chk) {
				// Reading a chunk
				if(me.halt)
					return false;
				me.j++;
				chk = new Uint8Array(chk);
				chk = me.toBitArrayCodec(chk);
				var chk_length = me.encryptChk(chk);
				console.log(me.file.name+' - Part '+me.j+' size : '+chk_length);
				me.l += chk_length;
				var pct = me.l/me.est_size*100;
				if(pct > 100)
					pct = 100;
				document.querySelector("#span_upload"+(me.i)).innerHTML = me.file.name+' : '+pct.toFixed(2)+'%';
			},
			error_callback: errorHandler
		});
	};

	Encryption.prototype.parseFile = function(file, options) {
		var opts       = typeof options === 'undefined' ? {} : options;
		var fileSize   = file.size;
		var chunkSize  = typeof opts['chunk_size'] === 'undefined' ?  64 * 1024 : parseInt(opts['chunk_size']); // bytes
		var binary     = typeof opts['binary'] === 'undefined' ? false : opts['binary'] == true;
		var offset     = 0;
		var self       = this; // we need a reference to the current object
		var readBlock  = null;
		var chunkReadCallback = typeof opts['chunk_read_callback'] === 'function' ? opts['chunk_read_callback'] : function() {};
		var chunkErrorCallback = typeof opts['error_callback'] === 'function' ? opts['error_callback'] : function() {};
		var success = typeof opts['success'] === 'function' ? opts['success'] : function() {};

		var onLoadHandler = function(evt) {
			var current_chk_length = evt.target.result.length;
			if(current_chk_length === undefined)
				current_chk_length = evt.loaded;

			if (evt.target.error == null && current_chk_length !== undefined) {
				offset += current_chk_length;
				chunkReadCallback(evt.target.result);
			} else {
				chunkErrorCallback(evt.target.error);
				return;
			}
			if (offset >= fileSize) {
				success(file);
				return;
			}

			readBlock(offset, chunkSize, file);
		}

		readBlock = function(_offset, length, _file) {
			var r = new FileReader();
			var blob = _file.slice(_offset, length + _offset);
			r.onload = onLoadHandler;
			if (binary) {
				r.readAsArrayBuffer(blob);
			} else {
				r.readAsText(blob);
			}
		}
		readBlock(offset, chunkSize, file);
	};

	Encryption.prototype.encryptChk = function(chk) {
		if(this.halt)
			return false;
		var me = this;

		var pack = function(c, s, a, i){ //ciphered_chk, salt, authentification data, initialization vector
			var c = sjcl.codec.base64.fromBits(c);
			var s = sjcl.codec.base64.fromBits(s);
			var a = sjcl.codec.base64.fromBits(a);
			var i = sjcl.codec.base64.fromBits(i);
			var t = c+":"+s+":"+a+":"+i;
			return t;
		}

		var initVector = sjcl.random.randomWords(4);
		var s = sjcl.mode.gcm.encrypt(this.enc, chk, initVector, this.aDATA, 128);
		s = pack(s, this.SALT, this.aDATA, initVector);

		var xhr = new XMLHttpRequest();
		xhr.open("POST", target+'/writeChunk', true);
		xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

		xhr.onreadystatechange = function() {
			if(xhr.status == 200 && xhr.readyState == 4) {
				if(xhr.responseText == 'error') {
					// Quota exceeded or unable to write
					me.halt = true;
					return false;
				}
				me.k++;
			}
		}
		xhr.send("filename="+this.file.name+"&data="+encodeURIComponent(s)+"&folder_id="+this.folder_id);
		return s.length;
	};

	return Encryption;
});
<commit_msg>auth data longer than before and SALT -> salt<commit_after>// Encryption module. Loaded in window.onload()
// When page is loaded : Encryption.checkAPI();
var Encryption = (function() {
	// Private
	var chunkSize = 1024 * 1024; // Size of one chunk in B
	var CEK = 'password'; // for tests
	var target = 'User';
	var est = 33.5; // Estimation of the difference between the file and encrypted file in %

	var errorHandler = function(e) {
		console.log("Error");
		console.log(e);
	};

	var time;

	// Constructor
	function Encryption(f, f_id, i, reload) {
		var me = this;

		if(reload === true)
			this.reload = true;
		else
			this.reload = false;

		this.folder_id = f_id;
		this.file = f;	// file.name, file.size
		this.est_size = Math.round(f.size*(1+est/100)); // Estimation of encrypted file size
		this.i = i; // Id of file, used only for displaying progress, different from database !
		this.j = 0; // Number of chunks read
		this.k = 0; // Number of chunks written
		this.l = 0; // Number of B written
		this.halt = false;

		this.aDATA = sjcl.random.randomWords(4);
		this.salt = sjcl.random.randomWords(2);
		this.key = sjcl.misc.pbkdf2(CEK, this.salt, 2000, 256);
		this.enc = new sjcl.cipher.aes(this.key);

		// Check status before uploading
		var xhr = new XMLHttpRequest();
		xhr.open("POST", target+'/getFileStatus', true);
		xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

		xhr.onreadystatechange = function() {
			// TODO : improve alert (only one) and confirm (yes, no, yes for all, no for all)
			if(xhr.status == 200 && xhr.readyState == 4) {
				if(xhr.responseText == '0') // File doesn't exist, it's ok
					me.read();
				else if(xhr.responseText == '1' || xhr.responseText == '2') // File exists
					if(confirm('The file '+f.name+' exists, do you want to replace it ?'))
						console.log('replace it'); //me.read(); // TODO
				else if(xhr.responseText == 'quota')
					alert('Quota exceeded !');
				else
					alert('Error');
			}
		}
		xhr.send("filename="+f.name+"&filesize="+f.size+"&folder_id="+f_id);
	}

	// Public
	Encryption.prototype.checkAPI = function() {
		if(window.File && window.FileReader && window.FileList && window.Blob) {
			reader = new FileReader();
			return true;
		}
		else {
			alert('The File APIs are not fully supported by your browser. Fallback required.');
			return false;
		}
	};

	Encryption.prototype.toBitArrayCodec = function(bytes) {
		/** Convert from an array of bytes to a bitArray. */
		var out = [], i, tmp=0;
		for (i=0; i<bytes.length; i++) {
			tmp = tmp << 8 | bytes[i];
			if ((i&3) === 3) {
				out.push(tmp);
				tmp = 0;
			}
		}
		if (i&3)
			out.push(sjcl.bitArray.partial(8*(i&3), tmp));
		return out;
	};

	Encryption.prototype.read = function() {
		var me = this;

		time = new Time();
		console.log('File size : '+this.file.size);
		console.log('File name : '+this.file.name);

		this.parseFile(this.file, {
			binary: true,
			chunk_size: chunkSize,
			success: function(i) {
				if(me.halt)
					return false;
				// Waiting end of the uploading process
				var timer = setInterval(function() {
					console.log("Waiting...");
					if(me.k >= me.j) {
						// Done, write "EOF" at the end of file
						clearInterval(timer);

						var xhr = new XMLHttpRequest();
						xhr.open("POST", target+'/writeChunk', true);
						xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

						xhr.onreadystatechange = function() {
							if(xhr.status == 200 && xhr.readyState == 4) {
								time.stop();//
								var node = document.querySelector("#div_upload"+(me.i));
								while(node.firstChild) // remove all children
									node.removeChild(node.firstChild);
								console.log("Split + encryption : "+time.elapsed()+" ms");//
								console.log("Splitted in "+me.j+" chunks !");
								if(me.reload)
									Folders.open(me.folder_id);
							}
						}
						xhr.send("filename="+me.file.name+"&data=EOF&folder_id="+me.folder_id);
					}
				}, 1000);
			},
			chunk_read_callback: function(chk) {
				// Reading a chunk
				if(me.halt)
					return false;
				me.j++;
				chk = new Uint8Array(chk);
				chk = me.toBitArrayCodec(chk);
				var chk_length = me.encryptChk(chk);
				console.log(me.file.name+' - Part '+me.j+' size : '+chk_length);
				me.l += chk_length;
				var pct = me.l/me.est_size*100;
				if(pct > 100)
					pct = 100;
				document.querySelector("#span_upload"+(me.i)).innerHTML = me.file.name+' : '+pct.toFixed(2)+'%';
			},
			error_callback: errorHandler
		});
	};

	Encryption.prototype.parseFile = function(file, options) {
		var opts       = typeof options === 'undefined' ? {} : options;
		var fileSize   = file.size;
		var chunkSize  = typeof opts['chunk_size'] === 'undefined' ?  64 * 1024 : parseInt(opts['chunk_size']); // bytes
		var binary     = typeof opts['binary'] === 'undefined' ? false : opts['binary'] == true;
		var offset     = 0;
		var self       = this; // we need a reference to the current object
		var readBlock  = null;
		var chunkReadCallback = typeof opts['chunk_read_callback'] === 'function' ? opts['chunk_read_callback'] : function() {};
		var chunkErrorCallback = typeof opts['error_callback'] === 'function' ? opts['error_callback'] : function() {};
		var success = typeof opts['success'] === 'function' ? opts['success'] : function() {};

		var onLoadHandler = function(evt) {
			var current_chk_length = evt.target.result.length;
			if(current_chk_length === undefined)
				current_chk_length = evt.loaded;

			if (evt.target.error == null && current_chk_length !== undefined) {
				offset += current_chk_length;
				chunkReadCallback(evt.target.result);
			} else {
				chunkErrorCallback(evt.target.error);
				return;
			}
			if (offset >= fileSize) {
				success(file);
				return;
			}

			readBlock(offset, chunkSize, file);
		}

		readBlock = function(_offset, length, _file) {
			var r = new FileReader();
			var blob = _file.slice(_offset, length + _offset);
			r.onload = onLoadHandler;
			if (binary) {
				r.readAsArrayBuffer(blob);
			} else {
				r.readAsText(blob);
			}
		}
		readBlock(offset, chunkSize, file);
	};

	Encryption.prototype.encryptChk = function(chk) {
		if(this.halt)
			return false;
		var me = this;

		var pack = function(c, s, a, i){ //ciphered_chk, salt, authentification data, initialization vector
			var c = sjcl.codec.base64.fromBits(c);
			var s = sjcl.codec.base64.fromBits(s);
			var a = sjcl.codec.base64.fromBits(a);
			var i = sjcl.codec.base64.fromBits(i);
			var t = c+":"+s+":"+a+":"+i;
			return t;
		}

		var initVector = sjcl.random.randomWords(4);
		var s = sjcl.mode.gcm.encrypt(this.enc, chk, initVector, this.aDATA, 128);
		s = pack(s, this.salt, this.aDATA, initVector);

		var xhr = new XMLHttpRequest();
		xhr.open("POST", target+'/writeChunk', true);
		xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");

		xhr.onreadystatechange = function() {
			if(xhr.status == 200 && xhr.readyState == 4) {
				if(xhr.responseText == 'error') {
					// Quota exceeded or unable to write
					me.halt = true;
					return false;
				}
				me.k++;
			}
		}
		xhr.send("filename="+this.file.name+"&data="+encodeURIComponent(s)+"&folder_id="+this.folder_id);
		return s.length;
	};

	return Encryption;
});
<|endoftext|>


<commit_before>const
	path = require('path'),
	fs = require('fs-extra-promise'),
	resolve = require('./resolve'),
	Declaration = require('./declaration'),
	Sugar = require('sugar'),
	$C = require('collection.js');

const filesCache = {};
async function getFile(path) {
	const {mtime} = await fs.statAsync(path);

	if (!filesCache[path] || !Sugar.Date.is(mtime, filesCache[path].mtime)) {
		filesCache[path] = {
			mtime,
			content: await fs.readFileAsync(path, 'utf-8')
		};
	}

	return filesCache[path].file;
}

class Block {
	static async get(name) {
		const indexContent = await getFile(
			path.join(resolve.block(name), 'index.js'),
			'utf-8'
		);

		return new this(new Declaration(indexContent));
	}

	static async getAll(names) {
		if (!names) {
			names = await fs.readdirAsync(resolve.block());
		}

		return $C(names)
			.async
			.reduce(
				(res, name, i, data, o) => {
					o.wait(this.get(name).then((block) => {
						res[i] = block;
					}));

					return res;
				},

				[]
			);
	}

	get name() {
		return this.declaration.name;
	}

	get type() {
		return this.declaration.type;
	}

	get parent() {
		return this.declaration.parent;
	}

	get mixin() {
		return this.declaration.mixin;
	}

	get dependencies() {
		return this.declaration.dependencies;
	}

	get libs() {
		return this.declaration.libs;
	}

	constructor(declaration) {
		this.declaration = declaration;
		Object.freeze(this);
	}

	async getParent() {
		return this.parent ?
			this.constructor.get(this.parent) :
			null;
	}

	async getDependencies(onlyOwn = false) {
		const names = Sugar.Array.clone(this.dependencies);

		if (!onlyOwn) {
			let parent = await this.getParent();

			while (parent) {
				Sugar.Array.insert(names, parent.dependencies, 0);
				parent = await parent.getParent();
			}
		}

		return this.constructor.getAll(Sugar.Array.unique(names));
	}

	async getLibs(onlyOwn = false) {
		const libs = Sugar.Array.clone(this.libs);

		if (!onlyOwn) {
			let parent = await this.getParent();

			while (parent) {
				Sugar.Array.insert(libs, parent.libs, 0);
				parent = await parent.getParent();
			}
		}

		return libs;
	}
}

module.exports = Block;
<commit_msg>:wrench:<commit_after>const
	path = require('path'),
	fs = require('fs-extra-promise'),
	resolve = require('./resolve'),
	Declaration = require('./declaration'),
	Sugar = require('sugar'),
	$C = require('collection.js');

const filesCache = {};
async function getFile(path) {
	const {mtime} = await fs.statAsync(path);

	if (!filesCache[path] || !Sugar.Date.is(mtime, filesCache[path].mtime)) {
		filesCache[path] = {
			mtime,
			content: await fs.readFileAsync(path, 'utf-8')
		};
	}

	return filesCache[path].content;
}

class Block {
	static async get(name) {
		const indexContent = await getFile(
			path.join(resolve.block(name), 'index.js'),
		);

		return new this(new Declaration(indexContent));
	}

	static async getAll(names) {
		if (!names) {
			names = await fs.readdirAsync(resolve.block());
		}

		return $C(names)
			.async
			.reduce(
				(res, name, i, data, o) => {
					o.wait(this.get(name).then((block) => {
						res[i] = block;
					}));

					return res;
				},

				[]
			);
	}

	get name() {
		return this.declaration.name;
	}

	get type() {
		return this.declaration.type;
	}

	get parent() {
		return this.declaration.parent;
	}

	get mixin() {
		return this.declaration.mixin;
	}

	get dependencies() {
		return this.declaration.dependencies;
	}

	get libs() {
		return this.declaration.libs;
	}

	constructor(declaration) {
		this.declaration = declaration;
		Object.freeze(this);
	}

	async getParent() {
		return this.parent ?
			this.constructor.get(this.parent) :
			null;
	}

	async getDependencies(onlyOwn = false) {
		const names = Sugar.Array.clone(this.dependencies);

		if (!onlyOwn) {
			let parent = await this.getParent();

			while (parent) {
				Sugar.Array.insert(names, parent.dependencies, 0);
				parent = await parent.getParent();
			}
		}

		return this.constructor.getAll(Sugar.Array.unique(names));
	}

	async getLibs(onlyOwn = false) {
		const libs = Sugar.Array.clone(this.libs);

		if (!onlyOwn) {
			let parent = await this.getParent();

			while (parent) {
				Sugar.Array.insert(libs, parent.libs, 0);
				parent = await parent.getParent();
			}
		}

		return libs;
	}
}

module.exports = Block;
<|endoftext|>