Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Factor out width-resizing logic for inline widgets into the InlineWidget base class #2285

Merged
merged 5 commits into from

2 participants

@njx
Owner
njx commented

This addresses #2221 and #2218.

As part of this, cleaned up some issues around how we're doing inheritance:

  • For #872, switched to using Object.create() to hook up prototypes (this avoids subtle bugs when binding event handlers in base classes).
  • Made it so all child classes call base class implementation for overridden functions (even if the base class impl is empty right now). The one exception is close(), which is a bit weird right now.
  • Changed the incorrect way we were using the parentClass pattern for supers--we were calling this.parentClass.myMethod.call(this), which doesn't work if the current method being called is on an intermediate class in the inheritance chain. Instead, it should be MySubclass.prototype.parentClass.myMethod.call(this).
  • In InlineColorEditor, eliminated the this.editor property in favor of using the this.hostEditor set up by the InlineWidget.load() method.

The issue with close() is that the base version in InlineWidget seems to assume that there is an _editorHasFocus() method on this, but InlineWidget doesn't actually define one. Need to figure out if this should be given a default implementation that just returns true. If so, then we could just eliminate close() from InlineImageWidget, and the dummy _editorHasFocus() implementation on InlineColorEditor.

@njx njx Factor out width-resizing logic for inline widgets into the InlineWid…
…get base class.

This addresses #2221 and #2218.
As part of this, cleaned up some issues around how we're doing inheritance:
* For #872, switched to using `Object.create()` to hook up prototypes
  (this avoids subtle bugs when binding event handlers in base classes).
* Made it so all child classes call base class implementation for overridden functions
  (even if the base class impl is empty right now). The one exception is `close()`, which
  is a bit weird right now--will file a separate issue on this.
9644ba9
@peterflynn peterflynn was assigned
@njx
Owner
njx commented

@peterflynn Would you mind taking a look at this one?

@peterflynn
Owner

#2137 gives us a later opportunity to clean up the close()/_editorHasFocus() assumption -- ideally we would just eliminate the need for removeInlineWidget()'s shouldMoveFocus arg altogether, which removes the need for _editorHasFocus() and InlineImageViewer's close() override in one fell swoop.

@peterflynn peterflynn commented on the diff
src/editor/MultiRangeInlineEditor.js
@@ -476,7 +465,7 @@ define(function (require, exports, module) {
// Ignore when the editor's content got lost due to a deleted file
if (cause && cause.type === "deleted") { return; }
// Else yield to the parent's implementation
- return this.parentClass._onLostContent.apply(this, arguments);
@peterflynn Owner

Would it be less bug-prone to have all the super calls be of this form? Otherwise anyone adding a new arg in the future must remember to either add it to the call() args or switch call() to apply().

@njx Owner
njx added a note

Good idea. I'll fix them up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
src/editor/MultiRangeInlineEditor.js
@@ -515,7 +504,7 @@ define(function (require, exports, module) {
*/
MultiRangeInlineEditor.prototype.sizeInlineWidgetToContents = function (force, ensureVisibility) {
// Size the code mirror editors height to the editor content
- this.parentClass.sizeInlineWidgetToContents.call(this, force);
+ MultiRangeInlineEditor.prototype.parentClass.sizeInlineWidgetToContents.call(this, force);
@peterflynn Owner

If we don't change this to apply(), should probably add a comment that ensureVisibility is an arg added by the subclass -- otherwise it looks like a bug that it's not being passed along.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
...nsions/samples/InlineImageViewer/InlineImageViewer.js
@@ -49,7 +49,7 @@ define(function (require, exports, module) {
InlineImageViewer.prototype.$image = null;
InlineImageViewer.prototype.load = function (hostEditor) {
- this.parentClass.load.call(this, hostEditor);
+ InlineImageViewer.prototype.parentClass.load.call(this, hostEditor);
this.$wrapperDiv = $(inlineEditorTemplate);
@peterflynn Owner

Shouldn't InlineImageViewier.onAdded() call up to the super method so that it gets proper width resizing?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@peterflynn peterflynn commented on the diff
src/file/NativeFileSystem.js
@@ -301,7 +301,7 @@ define(function (require, exports, module) {
NativeFileSystem.FileEntry = function (name) {
NativeFileSystem.Entry.call(this, name, false);
};
- NativeFileSystem.FileEntry.prototype = new NativeFileSystem.Entry();
+ NativeFileSystem.FileEntry.prototype = Object.create(NativeFileSystem.Entry.prototype);
@peterflynn Owner

Should these have prototype.parentClass and prototype.constructor set too? (I'm not actually sure I understand what function .constructor serves, but parentClass at least seems useful).

@peterflynn Owner

Or rather, setting prototype.constructor on a subclass is necessary if you want 'subclassInstance.constructor === Subclass' instead of '=== Superclass'. (I've yet to hear a satisfactory explanation of why this isn't needed for base classes, though... is the default prototype object special somehow?).

But anyway, it seems like we might as well set both here for completeness.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@peterflynn
Owner

@njx: Done reviewing

@njx
Owner

Fixes for all comments pushed. Ready for re-review.

@njx
Owner

Also, I added documentation tying together all the prototypal inheritance stuff to our "Brackets Coding Conventions" page--could you review it and see if it looks good to you? https://github.com/adobe/brackets/wiki/Brackets-Coding-Conventions (near the bottom)

@peterflynn

I just noticed InlineImageViewer seems to be slightly broken -- the height isn't tall enough to accommodate the image. Looks like reversing the two lines in _sizeEditorToContent() fixes it. I don't think this was caused by your changes, but would you mind fixing it up anyway?

@peterflynn

These need to be set on .prototype (ditto below for DirectoryEntry).

@peterflynn peterflynn commented on the diff
src/command/Menus.js
@@ -748,7 +748,7 @@ define(function (require, exports, module) {
},
false);
}
- ContextMenu.prototype = new Menu();
+ ContextMenu.prototype = Object.create(Menu.prototype);
@peterflynn Owner

ContextMenu is the only one of these that doesn't call its super constructor. But it easily could, since all Menu does is initialize this.id. Should we do that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@peterflynn
Owner

@njx: Done re-reviewing

@njx njx Made ContextMenu actually call its superclass constructor (instead of…
… assigning a new menu to this.menu, which isn't actually used).
6b93be0
@njx
Owner

Fixes pushed.

@peterflynn
Owner

Perfect, thanks for the changes. Docs on the wiki look good too. Merging...

@peterflynn peterflynn merged commit 00c5e6d into master
@peterflynn peterflynn referenced this pull request from a commit
Commit has since been removed from the repository and is no longer available.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Dec 6, 2012
  1. @njx

    Factor out width-resizing logic for inline widgets into the InlineWid…

    njx authored
    …get base class.
    
    This addresses #2221 and #2218.
    As part of this, cleaned up some issues around how we're doing inheritance:
    * For #872, switched to using `Object.create()` to hook up prototypes
      (this avoids subtle bugs when binding event handlers in base classes).
    * Made it so all child classes call base class implementation for overridden functions
      (even if the base class impl is empty right now). The one exception is `close()`, which
      is a bit weird right now--will file a separate issue on this.
  2. @njx

    Removed duplicate onClosed() call

    njx authored
  3. @njx

    Removed unnecessary self=this

    njx authored
Commits on Dec 11, 2012
  1. @njx

    Code review cleanups

    njx authored
  2. @njx

    Made ContextMenu actually call its superclass constructor (instead of…

    njx authored
    … assigning a new menu to this.menu, which isn't actually used).
This page is out of date. Refresh to see the latest.
View
5 src/command/Menus.js
@@ -728,8 +728,7 @@ define(function (require, exports, module) {
*
*/
function ContextMenu(id) {
- this.id = id;
- this.menu = new Menu(id);
+ Menu.apply(this, arguments);
var $newMenu = $("<li class='dropdown context-menu' id='" + StringUtils.jQueryIdEscape(id) + "'></li>"),
$popUp = $("<ul class='dropdown-menu'></ul>"),
@@ -748,7 +747,7 @@ define(function (require, exports, module) {
},
false);
}
- ContextMenu.prototype = new Menu();
+ ContextMenu.prototype = Object.create(Menu.prototype);
@peterflynn Owner

ContextMenu is the only one of these that doesn't call its super constructor. But it easily could, since all Menu does is initialize this.id. Should we do that?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
ContextMenu.prototype.constructor = ContextMenu;
ContextMenu.prototype.parentClass = Menu.prototype;
View
9 src/editor/InlineTextEditor.js
@@ -81,7 +81,7 @@ define(function (require, exports, module) {
/* @type {Array.<{Editor}>}*/
this.editors = [];
}
- InlineTextEditor.prototype = new InlineWidget();
+ InlineTextEditor.prototype = Object.create(InlineWidget.prototype);
InlineTextEditor.prototype.constructor = InlineTextEditor;
InlineTextEditor.prototype.parentClass = InlineWidget.prototype;
@@ -125,6 +125,8 @@ define(function (require, exports, module) {
* Called any time inline was closed, whether manually (via close()) or automatically
*/
InlineTextEditor.prototype.onClosed = function () {
+ InlineTextEditor.prototype.parentClass.onClosed.apply(this, arguments);
+
_syncGutterWidths(this.hostEditor);
this.editors.forEach(function (editor) {
@@ -170,6 +172,8 @@ define(function (require, exports, module) {
* editor is constructed and added to the DOM
*/
InlineTextEditor.prototype.onAdded = function () {
+ InlineTextEditor.prototype.parentClass.onAdded.apply(this, arguments);
+
this.editors.forEach(function (editor) {
editor.refresh();
});
@@ -260,7 +264,7 @@ define(function (require, exports, module) {
* @param {Editor} hostEditor
*/
InlineTextEditor.prototype.load = function (hostEditor) {
- this.hostEditor = hostEditor;
+ InlineTextEditor.prototype.parentClass.load.apply(this, arguments);
// TODO: incomplete impelementation. It's not clear yet if InlineTextEditor
// will fuction as an abstract class or as generic inline editor implementation
@@ -271,6 +275,7 @@ define(function (require, exports, module) {
* Called when the editor containing the inline is made visible.
*/
InlineTextEditor.prototype.onParentShown = function () {
+ InlineTextEditor.prototype.parentClass.onParentShown.apply(this, arguments);
// We need to call this explicitly whenever the host editor is reshown, since
// we don't actually resize the inline editor while its host is invisible (see
// isFullyVisible() check in sizeInlineWidgetToContents()).
View
37 src/editor/InlineWidget.js
@@ -51,6 +51,8 @@ define(function (require, exports, module) {
e.stopImmediatePropagation();
}
});
+
+ this.updateWidth = this.updateWidth.bind(this);
}
InlineWidget.prototype.htmlContent = null;
InlineWidget.prototype.$htmlContent = null;
@@ -64,6 +66,29 @@ define(function (require, exports, module) {
InlineWidget.prototype.height = 0;
/**
+ * Automatically updates the width of the inline editor when the parent editor's width changes due to
+ * edits or window resizes.
+ */
+ InlineWidget.prototype.updateWidth = function () {
+ // Set the minimum width of the widget (which doesn't include the padding) to the width
+ // of CodeMirror's linespace, so that the total width will be at least as large as the
+ // width of the host editor's code plus any internal padding required by the widget.
+ // We can't just set the min-width to 100% because that would be 100% of the clientWidth of
+ // the host editor, rather than the overall scroll width.
+ // We also can't just use the host editor's scrollWidth, because if the host editor's own
+ // content becomes less wide, our own width will continue to prop open the host editor's
+ // scrollWidth.
+ // So instead, we peg our width to the right edge of CodeMirror's lineSpace (which is its
+ // width plus its offset from the left edge of the $htmlContent container).
+ // If the lineSpace is less than the scroller's clientWidth, we want to use the clientWidth instead.
+ // This is a bit of a hack since it relies on knowing some detail about the innards of CodeMirror.
+ var lineSpace = this.hostEditor._getLineSpaceElement(),
+ scroller = this.hostEditor.getScrollerElement(),
+ minWidth = Math.max(scroller.clientWidth, $(lineSpace).offset().left - this.$htmlContent.offset().left + lineSpace.scrollWidth);
+ this.$htmlContent.css("min-width", minWidth + "px");
+ };
+
+ /**
* Closes this inline widget and all its contained Editors
*/
InlineWidget.prototype.close = function () {
@@ -76,7 +101,8 @@ define(function (require, exports, module) {
* Called any time inline is closed, whether manually or automatically
*/
InlineWidget.prototype.onClosed = function () {
- // do nothing - base implementation
+ $(this.hostEditor).off("change", this.updateWidth);
+ $(window).off("resize", this.updateWidth);
};
/**
@@ -84,7 +110,10 @@ define(function (require, exports, module) {
* focus or measuring content, which require htmlContent to be in the DOM tree.
*/
InlineWidget.prototype.onAdded = function () {
- // do nothing - base implementation
+ // Autosize the inline widget to the scrollable width of the main editor.
+ $(window).on("resize", this.updateWidth);
+ $(this.hostEditor).on("change", this.updateWidth);
+ window.setTimeout(this.updateWidth, 0);
};
/**
@@ -92,10 +121,6 @@ define(function (require, exports, module) {
*/
InlineWidget.prototype.load = function (hostEditor) {
this.hostEditor = hostEditor;
-
- // TODO: incomplete impelementation. It's not clear yet if InlineTextEditor
- // will fuction as an abstract class or as generic inline editor implementation
- // that just shows a range of text. See CSSInlineEditor.css for an implementation of load()
};
/**
View
24 src/editor/MultiRangeInlineEditor.js
@@ -95,7 +95,7 @@ define(function (require, exports, module) {
this._selectedRangeIndex = -1;
}
- MultiRangeInlineEditor.prototype = new InlineTextEditor();
+ MultiRangeInlineEditor.prototype = Object.create(InlineTextEditor.prototype);
MultiRangeInlineEditor.prototype.constructor = MultiRangeInlineEditor;
MultiRangeInlineEditor.prototype.parentClass = InlineTextEditor.prototype;
@@ -113,7 +113,7 @@ define(function (require, exports, module) {
*
*/
MultiRangeInlineEditor.prototype.load = function (hostEditor) {
- this.parentClass.load.call(this, hostEditor);
+ MultiRangeInlineEditor.prototype.parentClass.load.apply(this, arguments);
// Container to hold all editors
var self = this;
@@ -320,7 +320,7 @@ define(function (require, exports, module) {
*/
MultiRangeInlineEditor.prototype.onClosed = function () {
// Superclass onClosed() destroys editor
- this.parentClass.onClosed.call(this);
+ MultiRangeInlineEditor.prototype.parentClass.onClosed.apply(this, arguments);
// remove resize handlers for relatedContainer
$(this.hostEditor).off("change", this._updateRelatedContainer);
@@ -416,17 +416,6 @@ define(function (require, exports, module) {
// Add extra padding to the right edge of the widget to account for the range list.
this.$htmlContent.css("padding-right", this.$relatedContainer.outerWidth() + "px");
-
- // Set the minimum width of the widget (which doesn't include the padding) to the width
- // of CodeMirror's linespace, so that the total width will be at least as large as the
- // width of the host editor's code plus the padding for the range list. We need to do this
- // rather than just setting min-width to 100% because adding padding for the range list
- // actually pushes out the width of the container, so we would end up continuously
- // growing the overall width.
- // This is a bit of a hack since it relies on knowing some detail about the innards of CodeMirror.
- var lineSpace = this.hostEditor._getLineSpaceElement(),
- minWidth = $(lineSpace).offset().left - this.$htmlContent.offset().left + lineSpace.scrollWidth;
- this.$htmlContent.css("min-width", minWidth + "px");
};
/**
@@ -476,7 +465,7 @@ define(function (require, exports, module) {
// Ignore when the editor's content got lost due to a deleted file
if (cause && cause.type === "deleted") { return; }
// Else yield to the parent's implementation
- return this.parentClass._onLostContent.apply(this, arguments);
@peterflynn Owner

Would it be less bug-prone to have all the super calls be of this form? Otherwise anyone adding a new arg in the future must remember to either add it to the call() args or switch call() to apply().

@njx Owner
njx added a note

Good idea. I'll fix them up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ return MultiRangeInlineEditor.prototype.parentClass._onLostContent.apply(this, arguments);
};
/**
@@ -515,7 +504,8 @@ define(function (require, exports, module) {
*/
MultiRangeInlineEditor.prototype.sizeInlineWidgetToContents = function (force, ensureVisibility) {
// Size the code mirror editors height to the editor content
- this.parentClass.sizeInlineWidgetToContents.call(this, force);
+ // We use "call" rather than "apply" here since ensureVisibility was an argument added just for this override.
+ MultiRangeInlineEditor.prototype.parentClass.sizeInlineWidgetToContents.call(this, force);
// Size the widget height to the max between the editor content and the related ranges list
var widgetHeight = Math.max(this.$relatedContainer.find(".related").height(), this.$editorsDiv.height());
this.hostEditor.setInlineWidgetHeight(this, widgetHeight, ensureVisibility);
@@ -530,6 +520,7 @@ define(function (require, exports, module) {
* @override
*/
MultiRangeInlineEditor.prototype.refresh = function () {
+ MultiRangeInlineEditor.prototype.parentClass.refresh.apply(this, arguments);
this.sizeInlineWidgetToContents(true);
this._updateRelatedContainer();
this.editors.forEach(function (editor, j, arr) {
@@ -542,7 +533,6 @@ define(function (require, exports, module) {
* @returns {MultiRangeInlineEditor}
*/
function _getFocusedMultiRangeInlineEditor() {
-
var focusedMultiRangeInlineEditor = null,
result = EditorManager.getFocusedInlineWidget();
View
44 src/extensions/default/InlineColorEditor/InlineColorEditor.js
@@ -50,11 +50,7 @@ define(function (require, exports, module) {
this._handleColorChange = this._handleColorChange.bind(this);
this._handleHostDocumentChange = this._handleHostDocumentChange.bind(this);
- this._handleHostResize = this._handleHostResize.bind(this);
- $(window).on("resize", this._handleHostResize);
- window.setTimeout(this._handleHostResize, 0);
-
InlineWidget.call(this);
}
@@ -65,7 +61,7 @@ define(function (require, exports, module) {
*/
InlineColorEditor.COLOR_REGEX = /#[a-f0-9]{6}|#[a-f0-9]{3}|rgb\( ?\b([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\b ?, ?\b([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\b ?, ?\b([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\b ?\)|rgba\( ?\b([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\b ?, ?\b([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\b ?, ?\b([0-9]{1,2}|1[0-9]{2}|2[0-4][0-9]|25[0-5])\b ?, ?\b(1|0|0\.[0-9]{1,3}) ?\)|hsl\( ?\b([0-9]{1,2}|[12][0-9]{2}|3[0-5][0-9]|360)\b ?, ?\b([0-9]{1,2}|100)\b% ?, ?\b([0-9]{1,2}|100)\b% ?\)|hsla\( ?\b([0-9]{1,2}|[12][0-9]{2}|3[0-5][0-9]|360)\b ?, ?\b([0-9]{1,2}|100)\b% ?, ?\b([0-9]{1,2}|100)\b% ?, ?\b(1|0|0\.[0-9]{1,3}) ?\)/gi;
- InlineColorEditor.prototype = new InlineWidget();
+ InlineColorEditor.prototype = Object.create(InlineWidget.prototype);
InlineColorEditor.prototype.constructor = InlineColorEditor;
InlineColorEditor.prototype.parentClass = InlineWidget.prototype;
@@ -121,7 +117,7 @@ define(function (require, exports, module) {
// instead of two bookmarks to track the range. (In our current old version of
// CodeMirror v2, markText() isn't robust enough for this case.)
- var line = this.editor.document.getLine(start.line),
+ var line = this.hostEditor.document.getLine(start.line),
matches = line.substr(start.ch).match(InlineColorEditor.COLOR_REGEX);
// Note that end.ch is exclusive, so we don't need to add 1 before comparing to
@@ -129,7 +125,7 @@ define(function (require, exports, module) {
if (matches && (end.ch === undefined || end.ch - start.ch < matches[0].length)) {
end.ch = start.ch + matches[0].length;
this._endBookmark.clear();
- this._endBookmark = this.editor._codeMirror.setBookmark(end);
+ this._endBookmark = this.hostEditor._codeMirror.setBookmark(end);
}
if (end.ch === undefined) {
@@ -155,9 +151,9 @@ define(function (require, exports, module) {
if (!this._isHostChange) {
// Replace old color in code with the picker's color, and select it
this._isOwnChange = true;
- this.editor.document.replaceRange(colorString, range.start, range.end);
+ this.hostEditor.document.replaceRange(colorString, range.start, range.end);
this._isOwnChange = false;
- this.editor.setSelection(range.start, {
+ this.hostEditor.setSelection(range.start, {
line: range.start.line,
ch: range.start.ch + colorString.length
});
@@ -168,22 +164,14 @@ define(function (require, exports, module) {
};
/**
- * Update the width of the inline editor based on the host editor's width.
- */
- InlineColorEditor.prototype._handleHostResize = function () {
- this.$htmlContent.css("min-width", this.hostEditor.getScrollerElement().scrollWidth + "px");
- };
-
- /**
* @override
* @param {!Editor} hostEditor
*/
InlineColorEditor.prototype.load = function (hostEditor) {
- this.editor = hostEditor;
- this.parentClass.load.call(this, hostEditor);
+ InlineColorEditor.prototype.parentClass.load.apply(this, arguments);
// Create color picker control
- var allColorsInDoc = this.editor.document.getText().match(InlineColorEditor.COLOR_REGEX);
+ var allColorsInDoc = this.hostEditor.document.getText().match(InlineColorEditor.COLOR_REGEX);
var swatchInfo = this._collateColors(allColorsInDoc, MAX_USED_COLORS);
this.colorEditor = new ColorEditor(this.$htmlContent, this._color, this._handleColorChange, swatchInfo);
};
@@ -198,9 +186,9 @@ define(function (require, exports, module) {
* Perform sizing & focus once we've been added to Editor's DOM
*/
InlineColorEditor.prototype.onAdded = function () {
- this.parentClass.onAdded.call(this);
+ InlineColorEditor.prototype.parentClass.onAdded.apply(this, arguments);
- var doc = this.editor.document;
+ var doc = this.hostEditor.document;
doc.addRef();
$(doc).on("change", this._handleHostDocumentChange);
@@ -213,6 +201,8 @@ define(function (require, exports, module) {
* Called whenever the inline widget is closed, whether automatically or explicitly
*/
InlineColorEditor.prototype.onClosed = function () {
+ InlineColorEditor.prototype.parentClass.onClosed.apply(this, arguments);
+
if (this._startBookmark) {
this._startBookmark.clear();
}
@@ -220,13 +210,9 @@ define(function (require, exports, module) {
this._endBookmark.clear();
}
- var doc = this.editor.document;
+ var doc = this.hostEditor.document;
$(doc).off("change", this._handleHostDocumentChange);
doc.releaseRef();
-
- $(window).off("resize", this._handleHostResize);
-
- this.parentClass.onClosed.call(this);
};
InlineColorEditor.prototype._sizeEditorToContent = function () {
@@ -282,10 +268,6 @@ define(function (require, exports, module) {
* When text in the code editor changes, update color picker to reflect it
*/
InlineColorEditor.prototype._handleHostDocumentChange = function () {
- // Any host document change might change the scroll width, so we need to
- // recalculate our own width.
- this._handleHostResize();
-
// Don't push the change into the color editor if it came from the color editor.
if (this._isOwnChange) {
return;
@@ -293,7 +275,7 @@ define(function (require, exports, module) {
var range = this.getCurrentRange();
if (range) {
- var newColor = this.editor.document.getRange(range.start, range.end);
+ var newColor = this.hostEditor.document.getRange(range.start, range.end);
if (newColor !== this._color) {
this._isHostChange = true;
this.colorEditor.setColorFromString(newColor);
View
6 src/extensions/samples/InlineImageViewer/InlineImageViewer.js
@@ -39,7 +39,7 @@ define(function (require, exports, module) {
this.fullPath = fullPath;
InlineWidget.call(this);
}
- InlineImageViewer.prototype = new InlineWidget();
+ InlineImageViewer.prototype = Object.create(InlineWidget.prototype);
InlineImageViewer.prototype.constructor = InlineImageViewer;
InlineImageViewer.prototype.parentClass = InlineWidget.prototype;
@@ -49,7 +49,7 @@ define(function (require, exports, module) {
InlineImageViewer.prototype.$image = null;
InlineImageViewer.prototype.load = function (hostEditor) {
- this.parentClass.load.call(this, hostEditor);
+ InlineImageViewer.prototype.parentClass.load.apply(this, arguments);
this.$wrapperDiv = $(inlineEditorTemplate);
@@ -70,10 +70,12 @@ define(function (require, exports, module) {
};
InlineImageViewer.prototype.onAdded = function () {
+ InlineImageViewer.prototype.parentClass.onAdded.apply(this, arguments);
window.setTimeout(this._sizeEditorToContent.bind(this));
};
InlineImageViewer.prototype._sizeEditorToContent = function () {
+ // TODO: image might not be loaded yet--need to listen for load event and update then.
this.hostEditor.setInlineWidgetHeight(this, this.$wrapperDiv.height() + 20, true);
this.$image.css("opacity", 1);
};
View
12 src/file/NativeFileSystem.js
@@ -301,7 +301,9 @@ define(function (require, exports, module) {
NativeFileSystem.FileEntry = function (name) {
NativeFileSystem.Entry.call(this, name, false);
};
- NativeFileSystem.FileEntry.prototype = new NativeFileSystem.Entry();
+ NativeFileSystem.FileEntry.prototype = Object.create(NativeFileSystem.Entry.prototype);
@peterflynn Owner

Should these have prototype.parentClass and prototype.constructor set too? (I'm not actually sure I understand what function .constructor serves, but parentClass at least seems useful).

@peterflynn Owner

Or rather, setting prototype.constructor on a subclass is necessary if you want 'subclassInstance.constructor === Subclass' instead of '=== Superclass'. (I've yet to hear a satisfactory explanation of why this isn't needed for base classes, though... is the default prototype object special somehow?).

But anyway, it seems like we might as well set both here for completeness.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ NativeFileSystem.FileEntry.prototype.constructor = NativeFileSystem.FileEntry;
+ NativeFileSystem.FileEntry.prototype.parentClass = NativeFileSystem.Entry.prototype;
NativeFileSystem.FileEntry.prototype.toString = function () {
return "[FileEntry " + this.fullPath + "]";
@@ -421,7 +423,7 @@ define(function (require, exports, module) {
};
/**
- * Obtains the File objecte for a FileEntry object
+ * Obtains the File object for a FileEntry object
*
* @param {!function(File)} successCallback
* @param {!function(FileError)} errorCallback
@@ -535,7 +537,9 @@ define(function (require, exports, module) {
// TODO (issue #241): void removeRecursively (VoidCallback successCallback, optional ErrorCallback errorCallback);
};
- NativeFileSystem.DirectoryEntry.prototype = new NativeFileSystem.Entry();
+ NativeFileSystem.DirectoryEntry.prototype = Object.create(NativeFileSystem.Entry.prototype);
+ NativeFileSystem.DirectoryEntry.prototype.constructor = NativeFileSystem.DirectoryEntry;
+ NativeFileSystem.DirectoryEntry.prototype.parentClass = NativeFileSystem.Entry.prototype;
NativeFileSystem.DirectoryEntry.prototype.toString = function () {
return "[DirectoryEntry " + this.fullPath + "]";
@@ -849,7 +853,7 @@ define(function (require, exports, module) {
this.onloadend = null;
};
// TODO (issue #241): extend EventTarget (draft status, not implememnted in webkit)
- // NativeFileSystem.FileReader.prototype = new NativeFileSystem.EventTarget()
+ // NativeFileSystem.FileReader.prototype = Object.create(NativeFileSystem.EventTarget.prototype);
NativeFileSystem.FileReader.prototype.readAsArrayBuffer = function (blob) {
// TODO (issue #241): implement
Something went wrong with that request. Please try again.