<commit_before>(function ($) {
  "use strict";
  var global = window.ttplustree = {};

  global.rect_padding = 10;

  global.drawRectangle = function (jsav, rect, node1, node2) {
    var stoke = 2;
    var padding = global.rect_padding;
    var n1p = $(node1.array.element).position();
    var n2p = $(node2.array.element).position();
    var width = $(node1.array.element).outerWidth();
    var height = $(node1.array.element).outerHeight();

    var x = n1p.left - padding + 3;
    var y = n1p.top - padding + 3;
    var w = (n2p.left + width) - (n1p.left) + (padding * 2);
    var h = height + (padding * 2);

    if (rect) {
      rect.hide();
    }
    rect = jsav.g.rect(x, y, w, h);
    rect.addClass("node-split-rect");
    return rect;
  };

  global.drawLeafArrows = function (jsav, leafList, arrowList) {
    // Add as many elements to the leafs arrows arrays as there are leafs
    while (arrowList.length !== leafList.length) {
      if (arrowList.length < leafList.length) {
        arrowList.push(null);
      } else if (arrowList.length > leafList.length) {
        var edge = arrowList.pop();
        if (edge) {
          edge.hide();
        }
      }
    }

    // Draw the arrows
    for (var i = 0; i < leafList.length - 1; i++) {
      var p1 = $(leafList[i].array.element).position();
      var p2 = $(leafList[i + 1].array.element).position();
      var w1 = $(leafList[i].array.element).outerWidth();
      var h1 = $(leafList[i].array.element).outerHeight();
      var h2 = $(leafList[i + 1].array.element).outerHeight();

      var x1 = p1.left + w1,
        y1 = p1.top + (h1 / 2),
        x2 = p2.left,
        y2 = p2.top + (h2 / 2);

      if (!arrowList[i]) {
        arrowList[i] = jsav.g.line(x1, y1, x2, y2, {"arrow-end": "classic", "stroke-width": 3.0});
      } else {
        arrowList[i].movePoints([[0, x1, y1], [1, x2, y2]]);
      }
    }
  };

  global.newNode = function (jsav, keys, isLeaf, values) {
    if (isLeaf) {
      for (var i = 0; i < keys.length; i++) {
        keys[i] = keys[i] + '

' + values[i] + '
';
      }
    }
    var arr = jsav.ds.array(keys, {left: "0", top: "0"});
    if (isLeaf) {
      arr.element.addClass('leaf-node');
    } else {
      arr.element.addClass('internal-node');
    }
    return new global.node(jsav, arr, isLeaf).center();
  };

  global.node = function (jsav, arr, isLeaf) {
    this.jsav = jsav;
    this.array = arr;
    this.isLeaf = isLeaf;
    this.children = [];
    this.edges = [];
  };

  var nodeproto = global.node.prototype;
  nodeproto.value = function (idx, key, value) {
    if (!key && key !== "") {
      return this.array.value(idx);
    }
    if (this.isLeaf && value) {
      key = key + '

' + value + '
';
    }
    this.array.value(idx, key);
  };

  nodeproto.move = function (left, top) {
    this.array.css({"left": "+=" + left + "px", "top": "+=" + top + "px"});
  };

  nodeproto.center = function () {
    var canvas = $(this.array.element).parent();
    var cw = $(canvas).outerWidth();
    var aw = $(this.array.element).outerWidth();
    var left_offset = (cw / 2) - (aw / 2);
    this.array.css({left: left_offset + "px", top: "15px"});
    return this;
  };

  nodeproto.addChild = function (newChild) {
    this.children.push(newChild);
    this.edges.push(null);
    this.drawEdge(this.children.length - 1);
  };

  nodeproto.insertChild = function (idx, newChild) {
    this.children.splice(idx, 0, newChild);
    this.edges.splice(idx, 0, null);
  };

  nodeproto.removeChild = function (idx) {
    // Remove child and edge
    var child = this.children.splice(idx, 1);
    var edge = this.edges.splice(idx, 1);
    // Hide edge
    if (edge[0]) {
      edge[0].hide();
    }
    // Return child
    return child[0];
  };

  nodeproto.drawEdge = function (child_idx) {
    // Calculate edge position
    var pos = $(this.array.element).position();
    var c_pos = $(this.children[child_idx].array.element).position();
    var x1 = pos.left,
      y1 = pos.top,
      x2 = c_pos.left,
      y2 = c_pos.top;

    // Adjust coordinates to align edges with arrays
    var left_off = ($(this.array.element).outerWidth() / $(this.array.element).children('li').size()) * child_idx;
    var top_off = $(this.array.element).outerHeight();
    x1 += left_off;
    y1 += top_off;
    x2 += $(this.children[child_idx].array.element).outerWidth() / 2;
    y2 += 2;

    if (child_idx === 0) {
      x1 += 2;
      y1 -= 1;
    } else if (child_idx === 2) {
      x1 -= 2;
      y1 -= 1;
    }

    // Set edge to right position
    if (!this.edges[child_idx]) {
      this.edges[child_idx] = this.jsav.g.line(x1, y1, x2, y2);
    } else {
      this.edges[child_idx].movePoints([[0, x1, y1], [1, x2, y2]]);
    }
  };

  nodeproto.updateEdges = function (recursive) {
    for (var i = 0; i < this.edges.length; i++) {
      this.drawEdge(i);
      if (recursive) {
        this.children[i].updateEdges(recursive);
      }
    }
    return this;
  };

  nodeproto.getLeafs = function () {
    if (this.isLeaf) {
      return [this];
    } else {
      var result = [];
      for (var i = 0; i < this.children.length; i++) {
        result = result.concat(this.children[i].getLeafs());
      }
      return result;
    }
  };

  nodeproto.hideEdges = function () {
    for (var i = 0; i < this.edges.length; i++) {
      this.edges[i].hide();
    }
    return this;
  };

  nodeproto.hideEdge = function (idx) {
    this.edges[idx].hide();
  };

  nodeproto.showEdges = function () {
    for (var i = 0; i < this.edges.length; i++) {
      this.edges[i].show();
    }
    return this;
  };

  nodeproto.showEdge = function (idx) {
    this.edges[idx].show();
    return this;
  };

  nodeproto.highlightToggle = function () {
    if (this.array.isHighlight()) {
      this.array.unhighlight();
    } else {
      this.array.highlight();
    }
  };

  nodeproto.highlightToggleEdge = function (idx) {
    this.edges[idx].toggleClass('highlight-edge');
  };

  nodeproto.child = function (pos) {
    return this.children[pos];
  };

}(jQuery));<commit_msg>Add comments to helper methods for 2-3+ tree<commit_after>(function ($) {
  "use strict";
  var global = window.ttplustree = {};

  global.rect_padding = 10;

  // Draw rectangle around node1 and node2. Assumes that node1 is to the left
  // of node2 and that both nodes are horizontally aligned.
  global.drawRectangle = function (jsav, rect, node1, node2) {
    var padding = global.rect_padding;
    var n1p = $(node1.array.element).position();
    var n2p = $(node2.array.element).position();
    var width = $(node1.array.element).outerWidth();
    var height = $(node1.array.element).outerHeight();

    var x = n1p.left - padding + 3;
    var y = n1p.top - padding + 3;
    var w = (n2p.left + width) - (n1p.left) + (padding * 2);
    var h = height + (padding * 2);

    if (rect) {
      rect.hide();
    }
    rect = jsav.g.rect(x, y, w, h);
    rect.addClass("node-split-rect");
    return rect;
  };

  // Draw arrows between all leaf nodes.
  global.drawLeafArrows = function (jsav, leafList, arrowList) {
    // Add as many elements to the leafs arrows arrays as there are leafs
    while (arrowList.length !== leafList.length) {
      if (arrowList.length < leafList.length) {
        arrowList.push(null);
      } else if (arrowList.length > leafList.length) {
        var edge = arrowList.pop();
        if (edge) {
          edge.hide();
        }
      }
    }

    // Draw the arrows
    for (var i = 0; i < leafList.length - 1; i++) {
      var p1 = $(leafList[i].array.element).position();
      var p2 = $(leafList[i + 1].array.element).position();
      var w1 = $(leafList[i].array.element).outerWidth();
      var h1 = $(leafList[i].array.element).outerHeight();
      var h2 = $(leafList[i + 1].array.element).outerHeight();

      var x1 = p1.left + w1,
        y1 = p1.top + (h1 / 2),
        x2 = p2.left,
        y2 = p2.top + (h2 / 2);

      if (!arrowList[i]) {
        arrowList[i] = jsav.g.line(x1, y1, x2, y2, {"arrow-end": "classic", "stroke-width": 3.0});
      } else {
        arrowList[i].movePoints([[0, x1, y1], [1, x2, y2]]);
      }
    }
  };

  // Initialize a new tree node.
  global.newNode = function (jsav, keys, isLeaf, values) {
    if (isLeaf) {
      for (var i = 0; i < keys.length; i++) {
        keys[i] = keys[i] + '

' + values[i] + '
';
      }
    }
    var arr = jsav.ds.array(keys, {left: "0", top: "0"});
    if (isLeaf) {
      arr.element.addClass('leaf-node');
    } else {
      arr.element.addClass('internal-node');
    }
    return new global.node(jsav, arr, isLeaf).center();
  };

  // Node constructor.
  global.node = function (jsav, arr, isLeaf) {
    this.jsav = jsav;
    this.array = arr;
    this.isLeaf = isLeaf;
    this.children = [];
    this.edges = [];
  };

  // Add functions to node prototype.
  var nodeproto = global.node.prototype;

  // Get/Set node value.
  nodeproto.value = function (idx, key, value) {
    if (!key && key !== "") {
      return this.array.value(idx);
    }
    if (this.isLeaf && value) {
      key = key + '

' + value + '
';
    }
    this.array.value(idx, key);
  };

  // Shift the position of the node.
  nodeproto.move = function (left, top) {
    this.array.css({"left": "+=" + left + "px", "top": "+=" + top + "px"});
  };

  // Move the node horizontally to the center of the canvas.
  nodeproto.center = function () {
    var canvas = $(this.array.element).parent();
    var cw = $(canvas).outerWidth();
    var aw = $(this.array.element).outerWidth();
    var left_offset = (cw / 2) - (aw / 2);
    this.array.css({left: left_offset + "px", top: "15px"});
    return this;
  };

  // Add child node to this node.
  nodeproto.addChild = function (newChild) {
    this.children.push(newChild);
    this.edges.push(null);
    this.drawEdge(this.children.length - 1);
  };

  // Insert child node at specified index.
  nodeproto.insertChild = function (idx, newChild) {
    this.children.splice(idx, 0, newChild);
    this.edges.splice(idx, 0, null);
  };

  // Remove child at specified index.
  nodeproto.removeChild = function (idx) {
    // Remove child and edge
    var child = this.children.splice(idx, 1);
    var edge = this.edges.splice(idx, 1);
    // Hide edge
    if (edge[0]) {
      edge[0].hide();
    }
    // Return child
    return child[0];
  };

  // Draw edge from this node to child node.
  nodeproto.drawEdge = function (child_idx) {
    // Calculate edge position
    var pos = $(this.array.element).position();
    var c_pos = $(this.children[child_idx].array.element).position();
    var x1 = pos.left,
      y1 = pos.top,
      x2 = c_pos.left,
      y2 = c_pos.top;

    // Adjust coordinates to align edges with arrays
    var left_off = ($(this.array.element).outerWidth() / $(this.array.element).children('li').size()) * child_idx;
    var top_off = $(this.array.element).outerHeight();
    x1 += left_off;
    y1 += top_off;
    x2 += $(this.children[child_idx].array.element).outerWidth() / 2;
    y2 += 2;

    if (child_idx === 0) {
      x1 += 2;
      y1 -= 1;
    } else if (child_idx === 2) {
      x1 -= 2;
      y1 -= 1;
    }

    // Set edge to right position
    if (!this.edges[child_idx]) {
      this.edges[child_idx] = this.jsav.g.line(x1, y1, x2, y2);
    } else {
      this.edges[child_idx].movePoints([[0, x1, y1], [1, x2, y2]]);
    }
  };

  // Draw/Update all edges to all children of this node.
  nodeproto.updateEdges = function (recursive) {
    for (var i = 0; i < this.edges.length; i++) {
      this.drawEdge(i);
      if (recursive) {
        this.children[i].updateEdges(recursive);
      }
    }
    return this;
  };

  // Traverse tree and get all leafs recursively.
  nodeproto.getLeafs = function () {
    if (this.isLeaf) {
      return [this];
    } else {
      var result = [];
      for (var i = 0; i < this.children.length; i++) {
        result = result.concat(this.children[i].getLeafs());
      }
      return result;
    }
  };

  // Hide all edges.
  nodeproto.hideEdges = function () {
    for (var i = 0; i < this.edges.length; i++) {
      this.edges[i].hide();
    }
    return this;
  };

  // Hide edge at specified index.
  nodeproto.hideEdge = function (idx) {
    this.edges[idx].hide();
  };

  // Show all edges.
  nodeproto.showEdges = function () {
    for (var i = 0; i < this.edges.length; i++) {
      this.edges[i].show();
    }
    return this;
  };

  // Show edge at specified index.
  nodeproto.showEdge = function (idx) {
    this.edges[idx].show();
    return this;
  };

  // Toggle node highlighting.
  nodeproto.highlightToggle = function () {
    if (this.array.isHighlight()) {
      this.array.unhighlight();
    } else {
      this.array.highlight();
    }
  };

  // Toggle edge highlighting. Index specified which edge is highlighted.
  nodeproto.highlightToggleEdge = function (idx) {
    this.edges[idx].toggleClass('highlight-edge');
  };

  // Get child at specified index.
  nodeproto.child = function (pos) {
    return this.children[pos];
  };

}(jQuery));<|endoftext|>


<commit_before>(function($) {
	$.entwine('ss', function($) {
		$('.WidgetAreaEditor').entwine({
			onmatch: function() {
				var parentName=$(this).attr('name');
				this.rewriteWidgetAreaAttributes();

				var availableWidgets=$('#availableWidgets-'+$(this).attr('name')).children().each(function() {
					// Don't run on comments, whitespace, etc
					if($(this)[0].nodeType==1) {
						// Gotta change their ID's because otherwise we get clashes between two tabs
						$(this)[0].id=$(this)[0].id+'-'+parentName;
					}
				});

				var parentRef=$(this);

				// Used widgets are sortable
				$(this).find('.usedWidgets').sortable({
					opacity: 0.6,
					handle: '.handle',
					update: function (e, ui) {
						parentRef.updateWidgets(e, ui)
					},
					placeholder: 'ui-state-highlight',
					forcePlaceholderSize: true,
					start: function (e, ui) {
						htmleditors = $(e.srcElement).closest('.Widget').find('textarea.htmleditor');
						$.each(htmleditors, function (k, i) {
							tinyMCE.execCommand('mceRemoveControl', false, $(i).attr('id'));
						})
					},
					stop: function (e, ui) {
						htmleditors = $(e.srcElement).closest('.Widget').find('textarea.htmleditor');
						$.each(htmleditors, function (k, i) {
							tinyMCE.execCommand('mceAddControl', true, $(i).attr('id'));
						})
					}
				});

				// Figure out maxid, this is used when creating new widgets
				$(this).data('maxid', 0);

				var usedWidgets = $(this).find('.usedWidgets .Widget');
				usedWidgets.each(function() {
					var widget = $(this)[0];
					if(widget.id) {
						widgetid = widget.id.match(/Widget\[(.+?)\]\[([0-9]+)\]/i);
						if(widgetid && parseInt(widgetid[2]) > parseInt(parentRef.data('maxid'))) {
							parentRef.data('maxid', parseInt(widgetid[2]));
						}
					}
				});

				// Ensure correct sort values are written when page is saved
				// TODO Adjust to new event listeners
				$('.cms-container').bind('submitform', function(e) {parentRef.beforeSave(e)});
			},

			rewriteWidgetAreaAttributes: function() {
				var name = $(this).attr('name');

				var monkeyWith = function(widgets, name) {
					if (!widgets) {
						return;
					}

					widgets.each(function() {
						widget=$(this)[0];
						if (!widget.rewritten && (widget.id || widget.name)) {
							if (widget.id && widget.id.indexOf('Widget[') === 0) {
								var newValue = widget.id.replace(/Widget\[/, 'Widget['+name+'][');
								//console.log('Renaming '+widget.tagName+' ID '+widget.id+' to '+newValue);
								widget.id = newValue;
							}
							if (widget.name && widget.name.indexOf('Widget[') === 0) {
								var newValue = widget.name.replace(/Widget\[/, 'Widget['+name+'][');
								//console.log('Renaming '+widget.tagName+' Name '+widget.name+' to '+newValue);
								widget.name=newValue;
							}
							widget.rewritten='yes';
						}else {
							//console.log('Skipping '+(widget.id ? widget.id : (widget.name ? widget.name : 'unknown '+widget.tagName)));
						}
					});
				}

				monkeyWith($('#WidgetAreaEditor-'+name+' .Widget'), name);
				monkeyWith($('#WidgetAreaEditor-'+name+' .Widget *'), name);
			},

			beforeSave: function() {
				// Ensure correct sort values are written when page is saved
				var usedWidgets = $('#usedWidgets-'+$(this).attr('name'));
				if(usedWidgets) {
					this.sortWidgets();

					var children=usedWidgets.children();

					children.each(function() {
						if($(this).beforeSave) {
							$(this).beforeSave();
						}
					});
				}
			},

			addWidget: function(className, holder) {
				if($('#WidgetAreaEditor-'+holder).attr('maxwidgets')) {
					var maxCount = $('#WidgetAreaEditor-'+holder).attr('maxwidgets');
					var count = $('#usedWidgets-'+holder+' .Widget').length;
					if (count+1 > maxCount) {
						alert(ss.i18n._t('WidgetAreaEditor.TOOMANY'));
						return;
					}
				}

				var parentRef=$(this),
					locale = $(this).closest('form').find('input[name=Locale]').val();

				$.ajax({
					'url': 'WidgetController/EditableSegment/' + className,
					'success' : function(response) {parentRef.insertWidgetEditor(response)},
					'data' : {
						'locale' :  locale ,
					},
				});
			},

			updateWidgets: function(e, ui) {
				// Gotta get the name of the current dohickey based off the ID
				var name = $(this).attr('id').split('-').pop();

				var i=0;
				var usedWidgets = $('#usedWidgets-'+name).children().each(function() {
					var widget = $(this)[0];
					if(widget.id) {
						$(this).find('input[name='+widget.id.replace(/\]/g,'\\]').replace(/\[/g,'\\[')+'\\[Sort\\]]').val(i);
						i++;
					}
				});
			},

			insertWidgetEditor: function(response) {
				var usedWidgets = $('#usedWidgets-'+$(this).attr('name')).children();

				// Give the widget a unique id
				var newID=parseInt($(this).data('maxid'))+1;
				$(this).data('maxid', newID);

				var widgetContent = response.replace(/Widget\[0\]/gi, "Widget[new-" + (newID) + "]");
				$('#usedWidgets-'+$(this).attr('name')).append(widgetContent);

				this.rewriteWidgetAreaAttributes();
			},

			sortWidgets: function() {
				// Order the sort by the order the widgets are in the list
				$('#usedWidgets-'+$(this).attr('name')).children().each(function(i) {
						var div = $(this)[0];

						if(div.nodeName != '#comment') {
							var fields = div.getElementsByTagName('input');
							for(j = 0; field = fields.item(j); j++) {
								if(field.name == div.id + '[Sort]') {
									field.value = i;
								}
							}
						}
					});
			},

			deleteWidget: function(widgetToRemove) {
				// Remove a widget from the used widgets column
				widgetToRemove.remove();
			}
		});

		$('div.availableWidgets .Widget h3').entwine({
			onclick: function(event) {
				parts = $(this).parent().attr('id').split('-');
				var widgetArea = parts.pop();
				var className = parts.pop();
				$('#WidgetAreaEditor-'+widgetArea).addWidget(className, widgetArea);
			}
		});

		$('div.usedWidgets div.Widget').entwine({
			onmatch: function() {
				// Call deleteWidget when delete button is pushed
				$(this).find('span.widgetDelete').click(function() {
					$(this).closest('.WidgetAreaEditor').deleteWidget($(this).parent().parent());
				});
			}
		});
	})
})(jQuery);
<commit_msg>#125 - FIX: firefox support for disconnecting tinyMCE<commit_after>(function($) {
	$.entwine('ss', function($) {
		$('.WidgetAreaEditor').entwine({
			onmatch: function() {
				var parentName=$(this).attr('name');
				this.rewriteWidgetAreaAttributes();

				var availableWidgets=$('#availableWidgets-'+$(this).attr('name')).children().each(function() {
					// Don't run on comments, whitespace, etc
					if($(this)[0].nodeType==1) {
						// Gotta change their ID's because otherwise we get clashes between two tabs
						$(this)[0].id=$(this)[0].id+'-'+parentName;
					}
				});

				var parentRef=$(this);

				// Used widgets are sortable
				$(this).find('.usedWidgets').sortable({
					opacity: 0.6,
					handle: '.handle',
					update: function (e, ui) {
						parentRef.updateWidgets(e, ui)
					},
					placeholder: 'ui-state-highlight',
					forcePlaceholderSize: true,
					start: function (e, ui) {
						htmleditors = $(ui.item).closest('.Widget').find('textarea.htmleditor');
						$.each(htmleditors, function (k, i) {
							tinyMCE.execCommand('mceRemoveControl', false, $(i).attr('id'));
						})
					},
					stop: function (e, ui) {
						htmleditors = $(ui.item).closest('.Widget').find('textarea.htmleditor');
						$.each(htmleditors, function (k, i) {
							tinyMCE.execCommand('mceAddControl', true, $(i).attr('id'));
						})
					}
				});

				// Figure out maxid, this is used when creating new widgets
				$(this).data('maxid', 0);

				var usedWidgets = $(this).find('.usedWidgets .Widget');
				usedWidgets.each(function() {
					var widget = $(this)[0];
					if(widget.id) {
						widgetid = widget.id.match(/Widget\[(.+?)\]\[([0-9]+)\]/i);
						if(widgetid && parseInt(widgetid[2]) > parseInt(parentRef.data('maxid'))) {
							parentRef.data('maxid', parseInt(widgetid[2]));
						}
					}
				});

				// Ensure correct sort values are written when page is saved
				// TODO Adjust to new event listeners
				$('.cms-container').bind('submitform', function(e) {parentRef.beforeSave(e)});
			},

			rewriteWidgetAreaAttributes: function() {
				var name = $(this).attr('name');

				var monkeyWith = function(widgets, name) {
					if (!widgets) {
						return;
					}

					widgets.each(function() {
						widget=$(this)[0];
						if (!widget.rewritten && (widget.id || widget.name)) {
							if (widget.id && widget.id.indexOf('Widget[') === 0) {
								var newValue = widget.id.replace(/Widget\[/, 'Widget['+name+'][');
								//console.log('Renaming '+widget.tagName+' ID '+widget.id+' to '+newValue);
								widget.id = newValue;
							}
							if (widget.name && widget.name.indexOf('Widget[') === 0) {
								var newValue = widget.name.replace(/Widget\[/, 'Widget['+name+'][');
								//console.log('Renaming '+widget.tagName+' Name '+widget.name+' to '+newValue);
								widget.name=newValue;
							}
							widget.rewritten='yes';
						}else {
							//console.log('Skipping '+(widget.id ? widget.id : (widget.name ? widget.name : 'unknown '+widget.tagName)));
						}
					});
				}

				monkeyWith($('#WidgetAreaEditor-'+name+' .Widget'), name);
				monkeyWith($('#WidgetAreaEditor-'+name+' .Widget *'), name);
			},

			beforeSave: function() {
				// Ensure correct sort values are written when page is saved
				var usedWidgets = $('#usedWidgets-'+$(this).attr('name'));
				if(usedWidgets) {
					this.sortWidgets();

					var children=usedWidgets.children();

					children.each(function() {
						if($(this).beforeSave) {
							$(this).beforeSave();
						}
					});
				}
			},

			addWidget: function(className, holder) {
				if($('#WidgetAreaEditor-'+holder).attr('maxwidgets')) {
					var maxCount = $('#WidgetAreaEditor-'+holder).attr('maxwidgets');
					var count = $('#usedWidgets-'+holder+' .Widget').length;
					if (count+1 > maxCount) {
						alert(ss.i18n._t('WidgetAreaEditor.TOOMANY'));
						return;
					}
				}

				var parentRef=$(this),
					locale = $(this).closest('form').find('input[name=Locale]').val();

				$.ajax({
					'url': 'WidgetController/EditableSegment/' + className,
					'success' : function(response) {parentRef.insertWidgetEditor(response)},
					'data' : {
						'locale' :  locale ,
					},
				});
			},

			updateWidgets: function(e, ui) {
				// Gotta get the name of the current dohickey based off the ID
				var name = $(this).attr('id').split('-').pop();

				var i=0;
				var usedWidgets = $('#usedWidgets-'+name).children().each(function() {
					var widget = $(this)[0];
					if(widget.id) {
						$(this).find('input[name='+widget.id.replace(/\]/g,'\\]').replace(/\[/g,'\\[')+'\\[Sort\\]]').val(i);
						i++;
					}
				});
			},

			insertWidgetEditor: function(response) {
				var usedWidgets = $('#usedWidgets-'+$(this).attr('name')).children();

				// Give the widget a unique id
				var newID=parseInt($(this).data('maxid'))+1;
				$(this).data('maxid', newID);

				var widgetContent = response.replace(/Widget\[0\]/gi, "Widget[new-" + (newID) + "]");
				$('#usedWidgets-'+$(this).attr('name')).append(widgetContent);

				this.rewriteWidgetAreaAttributes();
			},

			sortWidgets: function() {
				// Order the sort by the order the widgets are in the list
				$('#usedWidgets-'+$(this).attr('name')).children().each(function(i) {
						var div = $(this)[0];

						if(div.nodeName != '#comment') {
							var fields = div.getElementsByTagName('input');
							for(j = 0; field = fields.item(j); j++) {
								if(field.name == div.id + '[Sort]') {
									field.value = i;
								}
							}
						}
					});
			},

			deleteWidget: function(widgetToRemove) {
				// Remove a widget from the used widgets column
				widgetToRemove.remove();
			}
		});

		$('div.availableWidgets .Widget h3').entwine({
			onclick: function(event) {
				parts = $(this).parent().attr('id').split('-');
				var widgetArea = parts.pop();
				var className = parts.pop();
				$('#WidgetAreaEditor-'+widgetArea).addWidget(className, widgetArea);
			}
		});

		$('div.usedWidgets div.Widget').entwine({
			onmatch: function() {
				// Call deleteWidget when delete button is pushed
				$(this).find('span.widgetDelete').click(function() {
					$(this).closest('.WidgetAreaEditor').deleteWidget($(this).parent().parent());
				});
			}
		});
	})
})(jQuery);
<|endoftext|>


<commit_before>(function (){
  /* ADAPTER
   *
   * This blanket.js adapter is designed to autostart coverage
   * immediately. The other side of this is handled from Cucumber
   *
   * Required blanket commands:
   * blanket.setupCoverage(); // Do it ASAP
   * blanket.onTestStart(); // Do it ASAP
   * blanket.onTestDone(); // After Scenario Hook
   * blanket.onTestsDone(); // After Scenario Hook
   */

  blanket.beforeStartTestRunner({
    callback: function() {
      blanket.setupCoverage();
      blanket.onTestStart();
    }
  });

  /* REPORTER
   *
   * Blanket.js docs speak of blanket.customReporter but
   * that doesn't actually work so we'll override defaultReporter
   */
  blanket.defaultReporter = function(coverage_results){
    window.COVERAGE_RESULTS = coverage_results; // We'll grab this on selenium side
  };
})();
<commit_msg>Update javascript blanket adapter to include sources data.<commit_after>(function (){
  /* ADAPTER
   *
   * This blanket.js adapter is designed to autostart coverage
   * immediately. The other side of this is handled from Cucumber
   *
   * Required blanket commands:
   * blanket.setupCoverage(); // Do it ASAP
   * blanket.onTestStart(); // Do it ASAP
   * blanket.onTestDone(); // After Scenario Hook (Not necessary)
   * blanket.onTestsDone(); // After Scenario Hook
   */

  blanket.beforeStartTestRunner({
    callback: function() {
      blanket.setupCoverage();
      blanket.onTestStart();
      window.CUCUMBER_BLANKET = {
        files: {},
        sources: {},
        done: false,
        is_setup: true
      };
    }
  });

  /* REPORTER
   *
   * Blanket.js docs speak of blanket.customReporter but
   * that doesn't actually work so we'll override defaultReporter
   */
  blanket.defaultReporter = function(coverage_results){
    window.CUCUMBER_BLANKET.files = coverage_results.files;
    // Strangely enough it looks like we need to iterate in order to grab the `source`
    // data which is necessary to know which lines of code are being reported on.
    var files = Object.keys(coverage_results.files);
    for (var i = 0, l = files.length; i < l; i ++) {
      var file = files[i];
      window.CUCUMBER_BLANKET.sources[file] = window.CUCUMBER_BLANKET.files[file].source;
    }
    window.CUCUMBER_BLANKET.done = true;
    // Now we can grab all this on the selenium side through window.CUCUMBER_BLANKET
  };
})();

<|endoftext|>


<commit_before>  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-47787341-2', 'codeu.eu');
  ga('send', 'pageview');
<commit_msg>Integrated origin/ready/lakpub<commit_after>  (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

  ga('create', 'UA-52125577-1', 'josra.org');
  ga('send', 'pageview');
<|endoftext|>


<commit_before>/**
 *  Copyright (c) 2010 Marat Nepomnyashy    maratbn@gmail
 *
 *  Module: FILEfox/components/nsFILEfox.js
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *      * Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above copyright
 *        notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 *      * Neither the name of the <organization> nor the
 *        names of its contributors may be used to endorse or promote products
 *        derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *  The XPCOM component 'nsFILEfox' is declared here.
 */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

nsFILEfoxTextFileOut_interfaces = [
                                    Components.interfaces.nsIFILEfoxTextFileOut,
                                    Components.interfaces.nsIFILEfoxTextFile,
                                    Components.interfaces.nsIClassInfo,
                                    Components.interfaces.nsISupports
                                ];

function nsFILEfoxTextFileOut() {
}

nsFILEfoxTextFileOut.prototype = {
    //  Interaface nsIClassInfo:
    classDescription:           "This XPCOM component is part of the FILEfox Firefox extension.",
    classID:                    Components.ID("{9d163612-2c51-430d-9460-62cb0f2ffe46}"),
    contractID:                 "@marat.nepomnyashy/ns_file_fox_text_file_out;1",
    flags:                      Components.interfaces.nsIClassInfo.DOM_OBJECT,
    implementationLanguage:     Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,

    getHelperForLanguage:       function(language) {
                                    return null;
                                },

    getInterfaces:              function(totalInterfaces) {
                                    totalInterfaces.value = nsFILEfoxTextFileOut_interfaces.length;
                                    return nsFILEfoxTextFileOut_interfaces;
                                },

    //  Interface nsISupports:
    QueryInterface:             XPCOMUtils.generateQI(nsFILEfoxTextFileOut_interfaces),

    // Interface nsIFILEfoxTextFile:
    /**
     *  The encoding with which this text file is encoded.
     */
    encoding:                   "",

    /**
     *  Total number of lines in the text file.
     *
     *  Have to store the text file line by line rather than in a single string, as otherwise a huge file requiring to
     *  be accomodated in a huge string would overwhelm the browser's JavaScript engine.
     */
    totalLines:                 0,

    /**
     *  Returns a single line out of the text file, including the line termination carriage return character sequence.
     *
     *  @param  indexLine           Number                  0-based index of the line.
     */
    getLine:                    function(indexLine) {
                                    return this._arrLines && this._arrLines[indexLine];
                                },

    setData:                    function(strEncoding, totalLines, arrLines) {
                                    this.encoding = strEncoding;
                                    this.totalLines = totalLines;
                                    this._arrLines = arrLines;
                                }
}

nsFILEfox_interfaces =          [
                                    Components.interfaces.nsIFILEfox,
                                    Components.interfaces.nsIClassInfo,
                                    Components.interfaces.nsISupports
                                ];

function nsFILEfox() {
}

nsFILEfox.prototype = {
    //  Interaface nsIClassInfo:
    classDescription:           "This XPCOM component is part of the FILEfox Firefox extension.",
    classID:                    Components.ID("{7faaf2e7-a039-4a86-89f7-1406110c908c}"),
    contractID:                 "@marat.nepomnyashy/ns_file_fox;1",
    flags:                      Components.interfaces.nsIClassInfo.DOM_OBJECT,
    implementationLanguage:     Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,

    getHelperForLanguage:       function(language) {
                                    return null;
                                },

    getInterfaces:              function(totalInterfaces) {
                                    totalInterfaces.value = nsFILEfox_interfaces.length;
                                    return nsFILEfox_interfaces;
                                },

    _xpcom_categories: [{
        category:               "JavaScript global property",
        entry:                  'nsFILEfox'
    }],

    //  Interface nsISupports:
    QueryInterface:             XPCOMUtils.generateQI(nsFILEfox_interfaces),

    // Interface nsIFILEfox:

    /**
     *  Returns the version of the currently installed FILEfox extension.
     */
    getVersion:                 function() {
                                    var application = this._obtainComponentService(
                                                                    null,
                                                                    '@mozilla.org/fuel/application;1',
                                                                    Components.interfaces.fuelIApplication);

                                    var extension = application && application.extensions && application.extensions.get('FILEfox@maratbn.com');
                                    return extension && extension.version;
                                },

    /**
     *  Causes the FILEfox extension to request from the user to manually select an ASCII text file to load.  The
     *  function will then initiate a synchroneous file loading process, and at the conclusion return an object
     *  corresponding to the 'nsIFILEfoxTextFile' contract with the file contents, or a falsy value on failure.
     *
     *  @param  strMessageToUser    String                  A textual request message to display to the user, possibly
     *                                                      explaining why the application is requesting an ASCII text
     *                                                      file.
     */
    requestASCIIFile:           function(strMessageToUser, observer) {
                                    // Get a reference to the DOM window to be able to communicate with the user:
                                    var window_mediator = this._obtainComponentService(
                                                                    null,
                                                                    '@mozilla.org/appshell/window-mediator;1',
                                                                    Components.interfaces.nsIWindowMediator);
                                    var window = window_mediator && window_mediator.getMostRecentWindow(null);
                                    if (!window) return null;

                                    if (!window.confirm(this._generateConfirmationMsg(window, strMessageToUser))) return null;

                                    // Obtain the user's Desktop directory:
                                    var directory_service = this._obtainComponentService(
                                                                    window,
                                                                    '@mozilla.org/file/directory_service;1',
                                                                    Components.interfaces.nsIProperties);
                                    if (!directory_service) return null;

                                    var fileDesktop = directory_service.get('Desk', Components.interfaces.nsIFile);
                                    if (!fileDesktop || !fileDesktop.path) {
                                        window.alert("nsFILEfox error:  Unable to determine the user's desktop directory.");
                                        return null;
                                    }

                                    // Display the file picker:
                                    const nsi_file_picker = Components.interfaces.nsIFilePicker;
                                    var file_picker = this._obtainComponentInstance(
                                                                    window,
                                                                    '@mozilla.org/filepicker;1',
                                                                    nsi_file_picker);
                                    if (!file_picker) return null;

                                    file_picker.init(window, "Loading an ASCII text file for website via the FILEfox Firefox extension.", nsi_file_picker.modeOpen);
                                    file_picker.appendFilters(nsi_file_picker.filterAll);

                                    var ret = file_picker.show();
                                    if (ret !== nsi_file_picker.returnOK) return null;

                                    var file = file_picker.file;
                                    if (!file || !file.path) {
                                        window.alert("nsFILEfox error:  Unable to determine which file the user has decided to open.");
                                        return null;
                                    }

                                    var file_input_stream = this._obtainComponentInstance(
                                                                    window,
                                                                    '@mozilla.org/network/file-input-stream;1',
                                                                    Components.interfaces.nsIFileInputStream);
                                    if (!file_input_stream) return null;

                                    file_input_stream.init(file, 1, 0, false);

                                    var converter_input_stream = this._obtainComponentInstance(
                                                                    window,
                                                                    '@mozilla.org/intl/converter-input-stream;1',
                                                                    Components.interfaces.nsIConverterInputStream);
                                    if (!converter_input_stream) return null;

                                    var strEncoding = 'us-ascii';

                                    converter_input_stream.init(
                                                            file_input_stream,
                                                            strEncoding,
                                                            file_input_stream.available(),
                                                            converter_input_stream.DEFAULT_REPLACEMENT_CHARACTER);

                                    var arrContents = [], totalRead = 0;
                                    for (var isThereMore = true; isThereMore;) {
                                        var objRead = {};
                                        var totalToRead = file_input_stream.available();
                                        isThereMore = converter_input_stream.readString(totalToRead, objRead);
                                        arrContents.push(objRead.value);

                                        totalRead += totalToRead;
                                    }

                                    converter_input_stream.close();

                                    var strContents = arrContents.join("");
                                    var arrLines = strContents.split(/(\r\n|\r|\n)/);

                                    var file_fox_text_file = this._obtainComponentInstance(
                                                                    window,
                                                                    '@marat.nepomnyashy/ns_file_fox_text_file_out;1',
                                                                    Components.interfaces.nsIFILEfoxTextFileOut);
                                    file_fox_text_file.setData(strEncoding, arrLines.length, arrLines);
                                    return file_fox_text_file;
                                },

    _generateConfirmationMsg:   function(window, strMessageToUser) {
                                    var arrMessageFromDOM = strMessageToUser && strMessageToUser.split(/\s/);
                                    var arrMessageFromDOMLines = [];
                                    for (var i = 0; i < arrMessageFromDOM.length;) {
                                        var line = "", maxlen = 75;
                                        for (; i < arrMessageFromDOM.length; i++) {
                                            if (line.length == 0 && arrMessageFromDOM[i].length >= maxlen) {
                                                line = arrMessageFromDOM[i];
                                                i++;
                                                break;
                                            } else if ((line.length + arrMessageFromDOM[i].length) >= maxlen) {
                                                break;
                                            } else {
                                                if (line.length > 0) line += " ";
                                                line += arrMessageFromDOM[i];
                                            }
                                        }
                                        if (line.length > 0) arrMessageFromDOMLines.push(line);
                                    }

                                    var arrMessage = [];
                                    arrMessage.push(        "A JavaScript application embedded in this website is requesting to load an ASCII text file through the FILEfox Firefox extension.  ");

                                    if (arrMessageFromDOMLines.length > 0) {
                                        arrMessage.push(    "Message from the JavaScript application:  ",
                                                            "\r\n\r\n");
                                        for (var i = 0; i < arrMessageFromDOMLines.length; i++) {
                                            arrMessage.push(" -->  ", arrMessageFromDOMLines[i], "\r\n");
                                        }
                                        arrMessage.push(    "\r\n",
                                                            "Use your discretion regardless of what the message above says.  ");
                                    } else {
                                        arrMessage.push(    "The application has not provided an explanation as to which file it is requesting, or why.  ",
                                                            "Therefore, continuing not recommended.  ");
                                    }
                                    arrMessage.push(        "\r\n\r\n",
                                                            "Do not load files containing authentication, operating system configuration, or financial information.  ",
                                                            "Make sure to read the information at [Tools -> FILEfox -> About] before using this feature.  ",
                                                            "\r\n\r\n",
                                                            "Are you sure you want to continue to the file selection dialog box?");

                                    return arrMessage.join("");
                                },

    _obtainComponentClass:      function(window, strComponentContractID) {
                                    var objComponent = Components.classes[strComponentContractID];
                                    if (!objComponent) {
                                        if (window) window.alert("nsFILEfox error:  Unable to obtain the XPCOM class with the contract ID of '" + strComponentContractID + "'.");
                                        return null;
                                    }
                                    return objComponent;
                                },

    _obtainComponentInstance:   function(window, strComponentContractID, objInterface) {
                                    try {
                                        var objComponent = this._obtainComponentClass(window, strComponentContractID);
                                        if (!objComponent) return null;

                                        var objInstance = objComponent.createInstance(objInterface);
                                        if (!objInstance) {
                                            if (window) window.alert("nsFILEfox error:  Unable to create an instance of the XPCOM class with the contract ID of '" + strComponentContractID + "'.");
                                            return null;
                                        }
                                        return objInstance;
                                    } catch (e) {
                                        if (window) {
                                            window.alert("nsFILEfox error:  Unable to create an instance of the XPCOM class with the contract ID of '" + strComponentContractID + "'.  Caught exception: " + e);
                                            return null;
                                        } else {
                                            throw e;
                                        }
                                    }
                                },

    _obtainComponentService:    function(window, strComponentContractID, objInterface) {
                                    try {
                                        var objComponent = this._obtainComponentClass(window, strComponentContractID);
                                        if (!objComponent) return null;

                                        var objService = objComponent.getService(objInterface);
                                        if (!objService) {
                                            if (window) window.alert("nsFILEfox error:  Unable to obtain the service of the XPCOM class with the contract ID of '" + strComponentContractID + "'.");
                                            return null;
                                        }
                                        return objService;
                                    } catch (e) {
                                        if (window) {
                                            window.alert("nsFILEfox error:  Unable to obtain the service of the XPCOM class with the contract ID of '" + strComponentContractID + "'.  Caught exception: " + e);
                                            return null;
                                        } else {
                                            throw e;
                                        }
                                    }
                                }
};

var components = [nsFILEfox, nsFILEfoxTextFileOut];
function NSGetModule(compMgr, fileSpec) {
    return XPCOMUtils.generateModule(components);
}
<commit_msg>Synced with the latest IDL file, now supporting the 'totalLetters' attribute.<commit_after>/**
 *  Copyright (c) 2010 Marat Nepomnyashy    maratbn@gmail
 *
 *  Module: FILEfox/components/nsFILEfox.js
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *      * Redistributions of source code must retain the above copyright
 *        notice, this list of conditions and the following disclaimer.
 *      * Redistributions in binary form must reproduce the above copyright
 *        notice, this list of conditions and the following disclaimer in the
 *        documentation and/or other materials provided with the distribution.
 *      * Neither the name of the <organization> nor the
 *        names of its contributors may be used to endorse or promote products
 *        derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 *  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *
 *  The XPCOM component 'nsFILEfox' is declared here.
 */
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");

nsFILEfoxTextFileReadOut_interfaces = [
                                    Components.interfaces.nsIFILEfoxTextFileReadOut,
                                    Components.interfaces.nsIFILEfoxTextFileRead,
                                    Components.interfaces.nsIFILEfoxTextFile,
                                    Components.interfaces.nsIClassInfo,
                                    Components.interfaces.nsISupports
                                ];

function nsFILEfoxTextFileReadOut() {
}

nsFILEfoxTextFileReadOut.prototype = {
    //  Interaface nsIClassInfo:
    classDescription:           "This XPCOM component is part of the FILEfox Firefox extension.",
    classID:                    Components.ID("{9d163612-2c51-430d-9460-62cb0f2ffe46}"),
    contractID:                 "@marat.nepomnyashy/ns_file_fox_text_file_read_out;1",
    flags:                      Components.interfaces.nsIClassInfo.DOM_OBJECT,
    implementationLanguage:     Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,

    getHelperForLanguage:       function(language) {
                                    return null;
                                },

    getInterfaces:              function(totalInterfaces) {
                                    totalInterfaces.value = nsFILEfoxTextFileReadOut_interfaces.length;
                                    return nsFILEfoxTextFileReadOut_interfaces;
                                },

    //  Interface nsISupports:
    QueryInterface:             XPCOMUtils.generateQI(nsFILEfoxTextFileReadOut_interfaces),

    // Interface nsIFILEfoxTextFile:
    /**
     *  The encoding with which this text file is encoded.
     */
    encoding:                   "",

    /**
     *  Total number of letters in the text file.
     */
    totalLetters:               0,

    /**
     *  Total number of lines in the text file.
     *
     *  Have to store the text file line by line rather than in a single string, as otherwise a huge file requiring to
     *  be accomodated in a huge string would overwhelm the browser's JavaScript engine.
     */
    totalLines:                 0,

    /**
     *  Returns a single line out of the text file, including the line termination carriage return character sequence.
     *
     *  @param  indexLine           Number                  0-based index of the line.
     */
    getLine:                    function(indexLine) {
                                    return this._arrLines && this._arrLines[indexLine];
                                },

    setData:                    function(strEncoding, totalLetters, totalLines, arrLines) {
                                    this.encoding = strEncoding;
                                    this.totalLetters = totalLetters;
                                    this.totalLines = totalLines;
                                    this._arrLines = arrLines;
                                }
}

nsFILEfox_interfaces =          [
                                    Components.interfaces.nsIFILEfox,
                                    Components.interfaces.nsIClassInfo,
                                    Components.interfaces.nsISupports
                                ];

function nsFILEfox() {
}

nsFILEfox.prototype = {
    //  Interaface nsIClassInfo:
    classDescription:           "This XPCOM component is part of the FILEfox Firefox extension.",
    classID:                    Components.ID("{7faaf2e7-a039-4a86-89f7-1406110c908c}"),
    contractID:                 "@marat.nepomnyashy/ns_file_fox;1",
    flags:                      Components.interfaces.nsIClassInfo.DOM_OBJECT,
    implementationLanguage:     Components.interfaces.nsIProgrammingLanguage.JAVASCRIPT,

    getHelperForLanguage:       function(language) {
                                    return null;
                                },

    getInterfaces:              function(totalInterfaces) {
                                    totalInterfaces.value = nsFILEfox_interfaces.length;
                                    return nsFILEfox_interfaces;
                                },

    _xpcom_categories: [{
        category:               "JavaScript global property",
        entry:                  'nsFILEfox'
    }],

    //  Interface nsISupports:
    QueryInterface:             XPCOMUtils.generateQI(nsFILEfox_interfaces),

    // Interface nsIFILEfox:

    /**
     *  Returns the version of the currently installed FILEfox extension.
     */
    getVersion:                 function() {
                                    var application = this._obtainComponentService(
                                                                    null,
                                                                    '@mozilla.org/fuel/application;1',
                                                                    Components.interfaces.fuelIApplication);

                                    var extension = application && application.extensions && application.extensions.get('FILEfox@maratbn.com');
                                    return extension && extension.version;
                                },

    /**
     *  Causes the FILEfox extension to request from the user to manually select an ASCII text file to load.  The
     *  function will then initiate a synchroneous file loading process, and at the conclusion return an object
     *  corresponding to the 'nsIFILEfoxTextFile' contract with the file contents, or a falsy value on failure.
     *
     *  @param  strMessageToUser    String                  A textual request message to display to the user, possibly
     *                                                      explaining why the application is requesting an ASCII text
     *                                                      file.
     */
    requestASCIIFile:           function(strMessageToUser, observer) {
                                    // Get a reference to the DOM window to be able to communicate with the user:
                                    var window_mediator = this._obtainComponentService(
                                                                    null,
                                                                    '@mozilla.org/appshell/window-mediator;1',
                                                                    Components.interfaces.nsIWindowMediator);
                                    var window = window_mediator && window_mediator.getMostRecentWindow(null);
                                    if (!window) return null;

                                    if (!window.confirm(this._generateConfirmationMsg(window, strMessageToUser))) return null;

                                    // Obtain the user's Desktop directory:
                                    var directory_service = this._obtainComponentService(
                                                                    window,
                                                                    '@mozilla.org/file/directory_service;1',
                                                                    Components.interfaces.nsIProperties);
                                    if (!directory_service) return null;

                                    var fileDesktop = directory_service.get('Desk', Components.interfaces.nsIFile);
                                    if (!fileDesktop || !fileDesktop.path) {
                                        window.alert("nsFILEfox error:  Unable to determine the user's desktop directory.");
                                        return null;
                                    }

                                    // Display the file picker:
                                    const nsi_file_picker = Components.interfaces.nsIFilePicker;
                                    var file_picker = this._obtainComponentInstance(
                                                                    window,
                                                                    '@mozilla.org/filepicker;1',
                                                                    nsi_file_picker);
                                    if (!file_picker) return null;

                                    file_picker.init(window, "Loading an ASCII text file for website via the FILEfox Firefox extension.", nsi_file_picker.modeOpen);
                                    file_picker.appendFilters(nsi_file_picker.filterAll);

                                    var ret = file_picker.show();
                                    if (ret !== nsi_file_picker.returnOK) return null;

                                    var file = file_picker.file;
                                    if (!file || !file.path) {
                                        window.alert("nsFILEfox error:  Unable to determine which file the user has decided to open.");
                                        return null;
                                    }

                                    var file_input_stream = this._obtainComponentInstance(
                                                                    window,
                                                                    '@mozilla.org/network/file-input-stream;1',
                                                                    Components.interfaces.nsIFileInputStream);
                                    if (!file_input_stream) return null;

                                    file_input_stream.init(file, 1, 0, false);

                                    var converter_input_stream = this._obtainComponentInstance(
                                                                    window,
                                                                    '@mozilla.org/intl/converter-input-stream;1',
                                                                    Components.interfaces.nsIConverterInputStream);
                                    if (!converter_input_stream) return null;

                                    var strEncoding = 'us-ascii';

                                    converter_input_stream.init(
                                                            file_input_stream,
                                                            strEncoding,
                                                            file_input_stream.available(),
                                                            converter_input_stream.DEFAULT_REPLACEMENT_CHARACTER);

                                    var arrContents = [], totalRead = 0;
                                    for (var isThereMore = true; isThereMore;) {
                                        var objRead = {};
                                        var totalToRead = file_input_stream.available();
                                        isThereMore = converter_input_stream.readString(totalToRead, objRead);
                                        arrContents.push(objRead.value);

                                        totalRead += totalToRead;
                                    }

                                    converter_input_stream.close();

                                    var strContents = arrContents.join("");
                                    var arrLines = strContents.split(/(\r\n|\r|\n)/);

                                    var file_fox_text_file = this._obtainComponentInstance(
                                                                    window,
                                                                    '@marat.nepomnyashy/ns_file_fox_text_file_read_out;1',
                                                                    Components.interfaces.nsIFILEfoxTextFileReadOut);
                                    file_fox_text_file.setData(strEncoding, strContents.length, arrLines.length, arrLines);
                                    return file_fox_text_file;
                                },

    _generateConfirmationMsg:   function(window, strMessageToUser) {
                                    var arrMessageFromDOM = strMessageToUser && strMessageToUser.split(/\s/);
                                    var arrMessageFromDOMLines = [];
                                    for (var i = 0; i < arrMessageFromDOM.length;) {
                                        var line = "", maxlen = 75;
                                        for (; i < arrMessageFromDOM.length; i++) {
                                            if (line.length == 0 && arrMessageFromDOM[i].length >= maxlen) {
                                                line = arrMessageFromDOM[i];
                                                i++;
                                                break;
                                            } else if ((line.length + arrMessageFromDOM[i].length) >= maxlen) {
                                                break;
                                            } else {
                                                if (line.length > 0) line += " ";
                                                line += arrMessageFromDOM[i];
                                            }
                                        }
                                        if (line.length > 0) arrMessageFromDOMLines.push(line);
                                    }

                                    var arrMessage = [];
                                    arrMessage.push(        "A JavaScript application embedded in this website is requesting to load an ASCII text file through the FILEfox Firefox extension.  ");

                                    if (arrMessageFromDOMLines.length > 0) {
                                        arrMessage.push(    "Message from the JavaScript application:  ",
                                                            "\r\n\r\n");
                                        for (var i = 0; i < arrMessageFromDOMLines.length; i++) {
                                            arrMessage.push(" -->  ", arrMessageFromDOMLines[i], "\r\n");
                                        }
                                        arrMessage.push(    "\r\n",
                                                            "Use your discretion regardless of what the message above says.  ");
                                    } else {
                                        arrMessage.push(    "The application has not provided an explanation as to which file it is requesting, or why.  ",
                                                            "Therefore, continuing not recommended.  ");
                                    }
                                    arrMessage.push(        "\r\n\r\n",
                                                            "Do not load files containing authentication, operating system configuration, or financial information.  ",
                                                            "Make sure to read the information at [Tools -> FILEfox -> About] before using this feature.  ",
                                                            "\r\n\r\n",
                                                            "Are you sure you want to continue to the file selection dialog box?");

                                    return arrMessage.join("");
                                },

    _obtainComponentClass:      function(window, strComponentContractID) {
                                    var objComponent = Components.classes[strComponentContractID];
                                    if (!objComponent) {
                                        if (window) window.alert("nsFILEfox error:  Unable to obtain the XPCOM class with the contract ID of '" + strComponentContractID + "'.");
                                        return null;
                                    }
                                    return objComponent;
                                },

    _obtainComponentInstance:   function(window, strComponentContractID, objInterface) {
                                    try {
                                        var objComponent = this._obtainComponentClass(window, strComponentContractID);
                                        if (!objComponent) return null;

                                        var objInstance = objComponent.createInstance(objInterface);
                                        if (!objInstance) {
                                            if (window) window.alert("nsFILEfox error:  Unable to create an instance of the XPCOM class with the contract ID of '" + strComponentContractID + "'.");
                                            return null;
                                        }
                                        return objInstance;
                                    } catch (e) {
                                        if (window) {
                                            window.alert("nsFILEfox error:  Unable to create an instance of the XPCOM class with the contract ID of '" + strComponentContractID + "'.  Caught exception: " + e);
                                            return null;
                                        } else {
                                            throw e;
                                        }
                                    }
                                },

    _obtainComponentService:    function(window, strComponentContractID, objInterface) {
                                    try {
                                        var objComponent = this._obtainComponentClass(window, strComponentContractID);
                                        if (!objComponent) return null;

                                        var objService = objComponent.getService(objInterface);
                                        if (!objService) {
                                            if (window) window.alert("nsFILEfox error:  Unable to obtain the service of the XPCOM class with the contract ID of '" + strComponentContractID + "'.");
                                            return null;
                                        }
                                        return objService;
                                    } catch (e) {
                                        if (window) {
                                            window.alert("nsFILEfox error:  Unable to obtain the service of the XPCOM class with the contract ID of '" + strComponentContractID + "'.  Caught exception: " + e);
                                            return null;
                                        } else {
                                            throw e;
                                        }
                                    }
                                }
};

var components = [nsFILEfox, nsFILEfoxTextFileReadOut];
function NSGetModule(compMgr, fileSpec) {
    return XPCOMUtils.generateModule(components);
}
<|endoftext|>


<commit_before>/**
* @file InitFunctions.js
* @brief Script des fonctions utilisées lors de l'initialisation
*/

/**
* @fn addFunctionToLinks Ajoute la fonction nameOfFunction aux liens présents sur la page
* @param {string} nameOfFunction Nom de la fonction devant être appelée
* @warning La fonction passée ne doit pas prendre d'arguments
* @TODO Ajouter des arguments à la fonction
*/
function addFunctionToLinks(nameOfFunction)
{
    // Recherche les liens faisant changer de page, et leur ajoute la recharge des lignes
    var allElements = document.getElementsByTagName('a');
    for (var i = allElements.length; i--;)
        if (allElements[i].getAttribute('href') === 'noscript.php' && typeof allElements[i].onclick === 'function')
        {
            allElements[i].setAttribute('onclick', allElements[i].getAttribute('onclick').substr(0, allElements[i].getAttribute('onclick').length - 13) + nameOfFunction + '(); return false;');
            allElements[i].setAttribute('href', '#');
        }

    // Recherche la checkBox faisant changer de page, et lui ajoute la recharge des lignes
    var checkBoxUpdate = document.getElementsByName('updated');
    for (i = checkBoxUpdate.length; i--;)
        if (typeof checkBoxUpdate[i].onchange === 'function')
        {
            checkBoxUpdate[i].setAttribute('onchange', checkBoxUpdate[i].getAttribute('onchange') + nameOfFunction + '();');
        }

    // Recherche la comboBox faisant changer de page, et lui ajoute la recharge des lignes et le changement d'état du langage
    var comboBox = document.getElementById('slang');
    if (comboBox && typeof comboBox.onchange === 'function')
    {
        comboBox.setAttribute('onchange', comboBox.getAttribute('onchange') + nameOfFunction + '();');
    }

    // Recherche la form de recherche et lui ajoute aussi la recharge de lignes
    var recherche = document.getElementById('filter');
    if (recherche && typeof recherche.onsubmit === 'function')
    {
        recherche.setAttribute('onsubmit', recherche.getAttribute('onsubmit').substr(0, recherche.getAttribute('onsubmit').length - 13) + nameOfFunction + '(); return false;');
    }
}

/**
* @fn changeButtonEvents Préfixe une fonction aux évènements des bouttons
*/
function changeButtonEvents()
{
    var listOfButton = document.getElementsByName('button');

    // Remplace pour chaque bouton
    for (var i = listOfButton.length; i--;)
        listOfButton[i].setAttribute('onclick', addStringBetween(listOfButton[i].getAttribute('onclick'), 'pre_', 11));

    // De même pour le bouton replace (après une recherche)
    var replaceButton = document.getElementById('replaceb');
    if (replaceButton !== null)
    {
        replaceButton.setAttribute('onclick', addStringBetween(replaceButton.getAttribute('onclick'), 'pre_', 12));
    }
}

                                        // Fonction de langue //
/**
* @fn changeLangIfEnglish Change le langue si l'anglais est poposé
*/
function changeLangIfEnglish()
{
    // Récupération de la comboBox
    var comboBox = document.getElementById('slang');

    // S'il n'y a pas de comboBox
    if (comboBox === null)
        return;

    var comboBoxOptions = comboBox.options;

    // Vérifie que l'anglais est présent
    for (var i = comboBoxOptions.length; i--;)
    {
        if (comboBoxOptions[i].value == 1)
        {
            console.log('[A7++] ' + loc.secondLangLoad);
            comboBoxOptions[i].selected = true;
            comboBox.onchange();
        }
    }
}

/**
* @fn linesChanged Met en cache les lignes et ajoute un évènement sur les liens
*/
function linesChanged()
{
    // Attend le chargement des séquences
    if (document.getElementById('lista').innerHTML === '')
    {
        setTimeout(linesChanged, 100);
        return;
    }

    console.log('[A7++] ' + loc.loadingLines);

    // Détourne les fonctions de base
    addFunctionToLinks('linesChanged');
    changeButtonEvents();

    // Si l'avancement n'est pas encore là
    if (document.getElementById('spanState') === null)
    {
        // Récupère la div parent des éléments à insérer
        var parentDiv = document.getElementsByClassName('tabel')[0].firstElementChild.children[1].children[1].firstElementChild;

        // Crée le span d'avancement et de lock des commentaires
        parentDiv.insertBefore(createCommentLockUtil(), parentDiv.firstElementChild);
        parentDiv.insertBefore(createStateUtil(), parentDiv.firstElementChild);

        // Ajoute l'indicateur HI en cas de sous-titre malentendants
        if(page.isHearingImpaired)
        {
            parentDiv.appendChild(createHIImg());
        }

        // Créé le span contenant les informations de l'extension
        parentDiv.appendChild(createA7Info());
    }

    // Actualise directement l'avancement
    updateStateOfTranslation();

    var headerRow = document.getElementById('trseqtop');

    // Création de la colonne compteur
    var counterCol    = document.createElement('td');
    var counterColDiv = document.createElement('div');
    counterCol.className      = 'NewsTitle';
    counterColDiv.title       = loc.charNumber;
    counterColDiv.textContent = loc.charNumberTiny;
    counterCol.appendChild(counterColDiv);

    // Ajoute avant la colonne Text la nouvelle colonne
    headerRow.insertBefore(counterCol, headerRow.lastElementChild);

    // Renomme les colonnes ou leur ajoute un titre
    headerRow.children[page.lock    ].firstElementChild.title = loc.sequence;
    headerRow.children[page.lock + 1].firstElementChild.title = loc.version;
    headerRow.children[page.lock + 4].firstElementChild.textContent += ' & ' + loc.duration + ' + RS Rating';

    // Récupère le nombre de lignes
    var tableOfLine = headerRow.parentElement;
    var lineNumbers = tableOfLine.childElementCount;

    var currentLine;

    for (var i = 1; i < lineNumbers; i++)
    {
        currentLine = tableOfLine.children[i];

        // Création de la cellule pour le nombre de caractères
        var cellTextCount = document.createElement('div');
        var cell          = document.createElement('td');
        cell.appendChild(cellTextCount);
        cell.setAttribute('class', 'counter');

        // Cellules utiles
        var timeCell = currentLine.children[page.lock + 4];
        var textCell = currentLine.lastElementChild;

        // Si la ligne a un texte modifiable
        if (currentLine.className === 'originalText')
        {
            var seqNumber = parseInt(currentLine.id.substr(5), 10);

            // Activation et mise en forme de la cellule
            if (timeCell.getAttribute('onclick') !== null)
            {
                // timeclick(...) => pre_timeclick(...)
                timeCell.setAttribute('onclick', 'pre_' + timeCell.getAttribute('onclick'));
            }

            timeCell.removeAttribute('onmouseout');
            timeCell.removeAttribute('onmouseover');

            // Activation et mise en forme de la cellule
            if (textCell.getAttribute('onclick') !== null)
            {
                textCell.setAttribute('onclick', 'pre_' + textCell.getAttribute('onclick'));
            }

            textCell.removeAttribute('onmouseout');
            textCell.removeAttribute('onmouseover');

            // Mise en forme
            timeCell.className = 'timeInitial ';
        }

        // Si le texte est non éditable
        else if (currentLine.className === 'quotedText')
        {
            timeCell.className = 'quotedTime ';
        }

        // S'il est bloqué
        else if (currentLine.className === 'lockedText')
        {
            timeCell.className = 'lockedTime ';
        }

        // Ajout de la classe norsr
        timeCell.className += 'timeWithoutIndicator norsr';

        // Remplace les sauts de ligne +
 par uniquement

        textCell.innerHTML = textCell.innerHTML.replace(/\n/g, '');

        // Longueur des lignes
        var charPerLine = charCount(textCell.innerHTML.split('
'), false);

        // Ajoute les compteurs de caractères des différentes lignes
        updateCharCountCell(cellTextCount, charPerLine);

        // Ajoute la cellule des compteurs dans la ligne
        currentLine.insertBefore(cell, textCell);

        // Récupère la durée
        var duration = getDurationFromTime(timeCell.innerHTML.split(' --> '));

        // Récupère le RS Rating de la séquence
        var index = getRSRatingIndex(charPerLine, duration);

        // Change la classe de la cellule de temps en fonction du RS Rating
        updateTimeCellClass(timeCell, index, duration);
    }

    // On ajoute les informations dans la légende
    var lista = document.getElementById('lista');

    if (lista)
    {
        var charNum = document.createElement('b');
        var rs      = document.createElement('b');

        var charNumText = document.createTextNode(loc.charNumber);
        var rsText      = document.createTextNode('Reading Speed ' + loc.rSLegend);

        charNum.textContent = '(' + loc.charNumberTiny + ') ';
        rs.textContent      = ' (RS) ';

        lista.appendChild(charNum);
        lista.appendChild(charNumText);
        lista.appendChild(rs);
        lista.appendChild(rsText);

    // Rend visible le tableau des séquences maintenant que le chargement est terminé
    lista.children[0].style.setProperty('visibility', 'visible');
    lista.children[1].style.setProperty('visibility', 'visible');
    }
}

/**
* @fn requestHICheck Engage la requête ajax pour la verification de version
*/
function requestHICheck()
{
    // Récupère les infos
    var episodeUrl = document.getElementsByClassName('tabel')[0].firstElementChild.children[1].children[1].firstElementChild.lastElementChild.firstElementChild.href;

    // Envoie la requête
    ajax('GET', episodeUrl, '', post_requestHICheck, null, null);
}

/**
* @fn post_requestHICheck Récupère les données de l'épisode et vérifie l'il est en HI
*/
function post_requestHICheck(episodeHTMLString, isError)
{
    // Re-envoi la requête en cas d'échec
    if (isError)
    {
        requestHICheck();
        return;
    }

    // Info et stockage
    var currentUrl = window.location.href,
        episodeHTML = document.createElement('html'),
        imgs = null;

    // De chaine à objet
    episodeHTML.innerHTML = episodeHTMLString;

    // Repère le lien de l'épisode
    var links = episodeHTML.getElementsByTagName('a');
    for (var i = 0; i < links.length; i++)
    {
        if (links[i].href === currentUrl)
        {
            // Récupère les indicateurs
            imgs = links[i].parentElement.previousElementSibling.getElementsByTagName('img');
            break;
        }
    }

    // Vérifie la présence du hearingImpaired
    for (i = 0; i < imgs.length; i++)
    {
        if (imgs[i].src === 'http://www.addic7ed.com/images/hi.jpg')
        {
            // Ajoute le logo et met à jour la variable page
            var parentDiv = document.getElementsByClassName('tabel')[0].firstElementChild.children[1].children[1].firstElementChild;

            if(parentDiv.lastElementChild.id !== 'hearingImpaired')
            {
                parentDiv.appendChild(createHIImg());
            }

            page.isHearingImpaired = true;
            break;
        }
    }

    console.log('[A7++] ' + loc.HIStatusLoaded);
}
<commit_msg>Fix: possible crash<commit_after>/**
* @file InitFunctions.js
* @brief Script des fonctions utilisées lors de l'initialisation
*/

/**
* @fn addFunctionToLinks Ajoute la fonction nameOfFunction aux liens présents sur la page
* @param {string} nameOfFunction Nom de la fonction devant être appelée
* @warning La fonction passée ne doit pas prendre d'arguments
* @TODO Ajouter des arguments à la fonction
*/
function addFunctionToLinks(nameOfFunction)
{
    // Recherche les liens faisant changer de page, et leur ajoute la recharge des lignes
    var allElements = document.getElementsByTagName('a');
    for (var i = allElements.length; i--;)
        if (allElements[i].getAttribute('href') === 'noscript.php' && typeof allElements[i].onclick === 'function')
        {
            allElements[i].setAttribute('onclick', allElements[i].getAttribute('onclick').substr(0, allElements[i].getAttribute('onclick').length - 13) + nameOfFunction + '(); return false;');
            allElements[i].setAttribute('href', '#');
        }

    // Recherche la checkBox faisant changer de page, et lui ajoute la recharge des lignes
    var checkBoxUpdate = document.getElementsByName('updated');
    for (i = checkBoxUpdate.length; i--;)
        if (typeof checkBoxUpdate[i].onchange === 'function')
        {
            checkBoxUpdate[i].setAttribute('onchange', checkBoxUpdate[i].getAttribute('onchange') + nameOfFunction + '();');
        }

    // Recherche la comboBox faisant changer de page, et lui ajoute la recharge des lignes et le changement d'état du langage
    var comboBox = document.getElementById('slang');
    if (comboBox && typeof comboBox.onchange === 'function')
    {
        comboBox.setAttribute('onchange', comboBox.getAttribute('onchange') + nameOfFunction + '();');
    }

    // Recherche la form de recherche et lui ajoute aussi la recharge de lignes
    var recherche = document.getElementById('filter');
    if (recherche && typeof recherche.onsubmit === 'function')
    {
        recherche.setAttribute('onsubmit', recherche.getAttribute('onsubmit').substr(0, recherche.getAttribute('onsubmit').length - 13) + nameOfFunction + '(); return false;');
    }
}

/**
* @fn changeButtonEvents Préfixe une fonction aux évènements des bouttons
*/
function changeButtonEvents()
{
    var listOfButton = document.getElementsByName('button');

    // Remplace pour chaque bouton
    for (var i = listOfButton.length; i--;)
        listOfButton[i].setAttribute('onclick', addStringBetween(listOfButton[i].getAttribute('onclick'), 'pre_', 11));

    // De même pour le bouton replace (après une recherche)
    var replaceButton = document.getElementById('replaceb');
    if (replaceButton !== null)
    {
        replaceButton.setAttribute('onclick', addStringBetween(replaceButton.getAttribute('onclick'), 'pre_', 12));
    }
}

                                        // Fonction de langue //
/**
* @fn changeLangIfEnglish Change le langue si l'anglais est poposé
*/
function changeLangIfEnglish()
{
    // Récupération de la comboBox
    var comboBox = document.getElementById('slang');

    // S'il n'y a pas de comboBox
    if (comboBox === null)
        return;

    var comboBoxOptions = comboBox.options;

    // Vérifie que l'anglais est présent
    for (var i = comboBoxOptions.length; i--;)
    {
        if (comboBoxOptions[i].value == 1)
        {
            console.log('[A7++] ' + loc.secondLangLoad);
            comboBoxOptions[i].selected = true;
            comboBox.onchange();
        }
    }
}

/**
* @fn linesChanged Met en cache les lignes et ajoute un évènement sur les liens
*/
function linesChanged()
{
    // Attend le chargement des séquences
    if (document.getElementById('lista').innerHTML === '')
    {
        setTimeout(linesChanged, 100);
        return;
    }

    console.log('[A7++] ' + loc.loadingLines);

    // Détourne les fonctions de base
    addFunctionToLinks('linesChanged');
    changeButtonEvents();

    // Si l'avancement n'est pas encore là
    if (document.getElementById('spanState') === null)
    {
        // Récupère la div parent des éléments à insérer
        var parentDiv = document.getElementsByClassName('tabel')[0].firstElementChild.children[1].children[1].firstElementChild;

        // Crée le span d'avancement et de lock des commentaires
        parentDiv.insertBefore(createCommentLockUtil(), parentDiv.firstElementChild);
        parentDiv.insertBefore(createStateUtil(), parentDiv.firstElementChild);

        // Ajoute l'indicateur HI en cas de sous-titre malentendants
        if(page.isHearingImpaired)
        {
            parentDiv.appendChild(createHIImg());
        }

        // Créé le span contenant les informations de l'extension
        parentDiv.appendChild(createA7Info());
    }

    // Actualise directement l'avancement
    updateStateOfTranslation();

    var headerRow = document.getElementById('trseqtop');

    // Création de la colonne compteur
    var counterCol    = document.createElement('td');
    var counterColDiv = document.createElement('div');
    counterCol.className      = 'NewsTitle';
    counterColDiv.title       = loc.charNumber;
    counterColDiv.textContent = loc.charNumberTiny;
    counterCol.appendChild(counterColDiv);

    // Ajoute avant la colonne Text la nouvelle colonne
    headerRow.insertBefore(counterCol, headerRow.lastElementChild);

    // Renomme les colonnes ou leur ajoute un titre
    headerRow.children[page.lock    ].firstElementChild.title = loc.sequence;
    headerRow.children[page.lock + 1].firstElementChild.title = loc.version;
    headerRow.children[page.lock + 4].firstElementChild.textContent += ' & ' + loc.duration + ' + RS Rating';

    // Récupère le nombre de lignes
    var tableOfLine = headerRow.parentElement;
    var lineNumbers = tableOfLine.childElementCount;

    var currentLine;

    for (var i = 1; i < lineNumbers; i++)
    {
        currentLine = tableOfLine.children[i];

        // Création de la cellule pour le nombre de caractères
        var cellTextCount = document.createElement('div');
        var cell          = document.createElement('td');
        cell.appendChild(cellTextCount);
        cell.setAttribute('class', 'counter');

        // Cellules utiles
        var timeCell = currentLine.children[page.lock + 4];
        var textCell = currentLine.lastElementChild;

        // Si la ligne a un texte modifiable
        if (currentLine.className === 'originalText')
        {
            var seqNumber = parseInt(currentLine.id.substr(5), 10);

            // Activation et mise en forme de la cellule
            if (timeCell.getAttribute('onclick') !== null)
            {
                // timeclick(...) => pre_timeclick(...)
                timeCell.setAttribute('onclick', 'pre_' + timeCell.getAttribute('onclick'));
            }

            timeCell.removeAttribute('onmouseout');
            timeCell.removeAttribute('onmouseover');

            // Activation et mise en forme de la cellule
            if (textCell.getAttribute('onclick') !== null)
            {
                textCell.setAttribute('onclick', 'pre_' + textCell.getAttribute('onclick'));
            }

            textCell.removeAttribute('onmouseout');
            textCell.removeAttribute('onmouseover');

            // Mise en forme
            timeCell.className = 'timeInitial ';
        }

        // Si le texte est non éditable
        else if (currentLine.className === 'quotedText')
        {
            timeCell.className = 'quotedTime ';
        }

        // S'il est bloqué
        else if (currentLine.className === 'lockedText')
        {
            timeCell.className = 'lockedTime ';
        }

        // Ajout de la classe norsr
        timeCell.className += 'timeWithoutIndicator norsr';

        // Remplace les sauts de ligne +
 par uniquement

        textCell.innerHTML = textCell.innerHTML.replace(/\n/g, '');

        // Longueur des lignes
        var charPerLine = charCount(textCell.innerHTML.split('
'), false);

        // Ajoute les compteurs de caractères des différentes lignes
        updateCharCountCell(cellTextCount, charPerLine);

        // Ajoute la cellule des compteurs dans la ligne
        currentLine.insertBefore(cell, textCell);

        // Récupère la durée
        var duration = getDurationFromTime(timeCell.innerHTML.split(' --> '));

        // Récupère le RS Rating de la séquence
        var index = getRSRatingIndex(charPerLine, duration);

        // Change la classe de la cellule de temps en fonction du RS Rating
        updateTimeCellClass(timeCell, index, duration);
    }

    // On ajoute les informations dans la légende
    var lista = document.getElementById('lista');

    if (lista)
    {
        var charNum = document.createElement('b');
        var rs      = document.createElement('b');

        var charNumText = document.createTextNode(loc.charNumber);
        var rsText      = document.createTextNode('Reading Speed ' + loc.rSLegend);

        charNum.textContent = '(' + loc.charNumberTiny + ') ';
        rs.textContent      = ' (RS) ';

        lista.appendChild(charNum);
        lista.appendChild(charNumText);
        lista.appendChild(rs);
        lista.appendChild(rsText);

    // Rend visible le tableau des séquences maintenant que le chargement est terminé
    lista.children[0].style.setProperty('visibility', 'visible');
    lista.children[1].style.setProperty('visibility', 'visible');
    }
}

/**
* @fn requestHICheck Engage la requête ajax pour la verification de version
*/
function requestHICheck()
{
    // Récupère les infos
    var episodeUrl = '',
        parent = document.getElementsByClassName('tabel')[0].firstElementChild.children[1].children[1].firstElementChild;
    for(var i = 0; i < parent.childElementCount; i++)
    {
        if(parent.children[i].nodeName === 'BIG')
        {
            episodeUrl = parent.children[i].firstElementChild.href;
            break;
        }
    }

    // Envoie la requête
    ajax('GET', episodeUrl, '', post_requestHICheck, null, null);
}

/**
* @fn post_requestHICheck Récupère les données de l'épisode et vérifie l'il est en HI
*/
function post_requestHICheck(episodeHTMLString, isError)
{
    // Re-envoi la requête en cas d'échec
    if (isError)
    {
        requestHICheck();
        return;
    }

    // Info et stockage
    var currentUrl = window.location.href,
        episodeHTML = document.createElement('html'),
        imgs = null;

    // De chaine à objet
    episodeHTML.innerHTML = episodeHTMLString;

    // Repère le lien de l'épisode
    var links = episodeHTML.getElementsByTagName('a');
    for (var i = 0; i < links.length; i++)
    {
        if (links[i].href === currentUrl)
        {
            // Récupère les indicateurs
            imgs = links[i].parentElement.previousElementSibling.getElementsByTagName('img');
            break;
        }
    }

    // Vérifie la présence du hearingImpaired
    for (i = 0; i < imgs.length; i++)
    {
        if (imgs[i].src === 'http://www.addic7ed.com/images/hi.jpg')
        {
            // Ajoute le logo et met à jour la variable page
            var parentDiv = document.getElementsByClassName('tabel')[0].firstElementChild.children[1].children[1].firstElementChild;

            if(parentDiv.lastElementChild.id !== 'hearingImpaired')
            {
                parentDiv.appendChild(createHIImg());
            }

            page.isHearingImpaired = true;
            break;
        }
    }

    console.log('[A7++] ' + loc.HIStatusLoaded);
}
<|endoftext|>