Although $.toJSON optimises heavily for modern browsers (it
becomes a direct reference to JSON.stringify), we still load the
extra plugin.
JSON is specified as part of ECMAScript 5, but most browsers
supported this one before they supported the rest of ES5.
http://caniuse.com/#search=JSON
Cut off for native JSON is IE7, Firefox 3.0 (3.6 supports it) and
Safari 3. Not any of our concern as VE will most likely never
support those (certainly not at this point in time, and less
likely as time goes on).
Change-Id: I4e8f26ac94763fa38d29e41264de0247f53a21e5
en.wikipedia.org has a template gala for edit notices with a whole
bunch of html framework outputted by default from
MediaWiki:Editnotice-0 (even if their underlying system has no
matches for the current page).
In the core editor from EditPage.php this isn't a problem as the
element is just idling hidden above the editor.
In the case of VisualEditor (where we have a custom delivery for
the edit notices) we don't want to say "1 notice available" on
every page, so we need to be smart and quickly walk the dom of the
notice, filter out invisible nodes, and if the resulting nodes
have no contents, ignore the notice all together.
Change-Id: I65447da8b88a9bae9c24ff155544ff66b3fe9100
The rules have changed, these constraints are no longer needed
and actually causing the table.diff to ignore the restrictions
and bump out of the container beyond the width of the window.
This restores the condition under which table.diff is displayed
by core EditPage.php.
Follows-up I5f59482f4db.
Change-Id: I456644bf14efab7dac351818d5c3bb69b9b3c993
Basically saveDialog-body now has three slides:
* review
* report
* save
There is a viewPage.swapSaveDialog method that is called like this
viewPage.swapSaveDialog( 'review' );
initially called from showSaveDialog.
Misc:
* Replaced more reused core message with a ve ones:
savearticle => visualeditor-savedialog-label-save
showdiff => (removed)
* Removed min-height from saveDialog. When slide-review is
load, it is very short and there shouldn't be 10em's of
whitespace below the loader + buttons.
To avoid problems with diff cache being cleared while looking
at the save dialog, we lock and unlock the surface.
We could later remove this as and optimise it as feature, but for
now this fixes a bug.
Change-Id: I5f59482f4db16264014720b199d7652843c36108
Drop "-down" class in favour of :active CSS pseudo-class.
* http://kimblim.dk/css-tests/selectors/
* http://www.quirksmode.org/css/contents.html
* http://caniuse.com/#search=css%202.1
Rename methods consistently to enableFoo and disableFoo.
Use mw.notify instead of mw.util.jsMessage (the latter takes a
string of html and parses it, instead of taking text).
Also, jsMessage is obsolete (legacy wrapper around mw.notify).
Rename slide-main to slide-save in preparation of other slides
and introduction of multi-step save dialog.
Re-introduce "disabled" state (not css, but actual state) so that
pressing "Show changes" multiple times will not spawn multiple
async operations. The save function guards against this by keeping
a static property in the internal helper method, but there are
still some operations happening between the button and that method
this should be guarded in the UI instead. Follows-up I67819168.
Change-Id: Idf0331377e6be814ccae853228d6159b4ad5a159
In the change: I6781916822b4173ba906b9bc4c341219fbf10d82
71b97ec45b was reversed when I submitted 1789545284
Change-Id: I6cc59a27817bfbe55c7cbf45bba746a4bd6c375f
I noticed this bug on [[List of Presidents of the United States]]. When
there's HTML that looks like "<td>Foo\n<meta/></td>", the converter will
collect the newline in wrappedWhitespace, then attempt to splice it out
and store it in internal data. But instead, it ends up splicing out the
/metaBlock element, which causes strange unbalanced input, which causes
an empty table in the node tree.
Change-Id: I79ed2fa9a834cc42759c7d21250d8842f563d38f
icons, comment.*, ve.ui.Icons-*
* Added comment icon
ve.init.mw.ViewPageTarget
* Refactored editNoticeButton into being just a tool
* Added feedback tool, which shares the editNoticeButton code
* Added feedback object construction in init constructor
* Added launching code to feedback tool
VisualEditor.i18n
* Renamed editnotices-button message to editnotices-tool to match changes in code
* Added feedback tool message
VisualEditor
* Added dependency on mediawiki.feedback
* Updated changed message key
* Added reference to new message
Change-Id: I813c89a505386a9b3206bfbcb176016e28a592cb
* Made buttons use shared CSS code
* Stopped using <button> elements and got all browsers looking the same
* Fixed focus on text area issue - had to let the stack clear first
Change-Id: I6781916822b4173ba906b9bc4c341219fbf10d82
This was removed in I0873d906c058203b83b8d4bbe5a4b274f05a26fd because I had fixed another cause of the recursion - this is still needed however because the following still happens:
1. Link inspector is opened away from a word, so it goes into a mode that will insert text based on the chosen target
2. The link inspector is closed, causing a context change when the new annotated text is inserted
3. The context change event triggers the link inspector to close, leading us back to step 2
4. Browser dies in infinite loop hell
We may be able to fix this in a different way, like performing the document changes after the inspector has already closed by running it in a timeout. In any case, this works for now, and we can improve the design of this area of the code later on.
Change-Id: I7f3c17dad08521bb1ae7c2a1e8a4e21e2c4ba210
In the event the page explodes from a huge js error, prevent
the iframe from reloading to slightly reduce the confusion of the
user.
Change-Id: I0c88678437f0bad994fa97f4df63d8b288f69e7a
-Added reset and hide calls to deactivate to prevent problems
with the save dialog if the user exits to the view.
-Remove unneeded teardown routines from cancel.
-Calling deactivate without override.
Change-Id: I888019146186fb7cbc1ee2b8efee9a0c45286c23
ve.Range
* Rewrote truncate so that it works as expected, truncation should always reduce the length using the start/end values, not the from/to values
ve.ui.Inspector
* Added a comment about where the name argument to onBeforeInspectorOpen comes from, since it's a little bit confusing on first read (and I wrote it!)
* Calling onInitialize, onOpen and onClose methods directly, since we need to control the before or after-ness of listeners getting in there and doing their stuff - plus it's more direct
* Removed onRemove stub, which is never actually called
* Added before/after versions of initialize, open and close events
* Got rid of recursion guard since we don't need it anymore thanks to changes made in ve.dm.Surface (see below)
ve.ui.Context
* Updated event names to deal with new before/after naming of initialize, open and close events
* Removed fade-in logic since fading in doesn't even work anymore - since now we now annotate first, then open the inspector, the menu will actually exist and be open when we open the inspector even though you don't see it because it's quickly obscured
ve.ui.LinkInspector
* Made fragments non-auto selecting, in the case of onInitialize we actually call select(), which is silly since we were using an auto-selecting fragment - it's clear that this was a mistake
ve.dm.Surface
* Moved locking (polling stop and start) to the far outside edges of the change method
* I need a lot of eyes and testing on this change, it seems OK to me, but I'm suspicious that it may have side effects
* What was happening is that selection changes were being applied and then the poll was picking them up, and then the selection was coming in again as a change, but it wasn't a change at all, it was just feedback - this change event was then closing the inspector the instant it was opened - the odd part was that this only occurred when you selected backwards, which seems to be caused by the range being normalized, so it looked like a new selection even though it wasn't
ve.dm.Document
* trimOuterSpace from Range didn't consider annotated spaces to be spaces, by using the [0] trick (first character of a plain text character string or first element in an annotated character's array both are the character's value - but elements don't have a property named '0' so it skips those safely as well) we can always get the right value for comparison
Change-Id: I0873d906c058203b83b8d4bbe5a4b274f05a26fd
Solution: do not call update (temporary solution to prevent error - however content will never be at offset 0 - so it should never hurt)
Change-Id: I9ed6f9fbea23d5e2e55c56f8483321442049bd51
Turned saveDialog-body into slide-based swapper.
Moved footer into saveDiaog-body so that the license text doesn't
stay under the diff-slide (and move body bottom padding to foot
top)
Wrapped buttons and title in a saveDialog-header and converted
closeButton from absolutely positioned to a floated layout.
This way the title doesn't need to be repositioned but will scooch
over if the prevButton gets shown/hidden.
Update API "diff" action to include table wrapper and table
header. Without it the mediawiki CSS for diff doesn't work
properly (needs colgroups for proper width of the "-" and "+" column etc)
Renamed -saving class to -disabled for consistency.
Set prop.disabled to really lock/unlock buttons, not just visual
(otherwise the click handlers are still triggered on click, can
potentially cause actions to be triggered when not expected)
Using a ve message for "Show your changes" title instead of
re-using core tooltip-savepage in a different context.
Diff slide triggers "auto width" on dialog (inline undo of width: 29em), keeping min-width, to allow it to expand as wide as needed.
Functions that I copied as base for onShowChanges and
onShowChangeError had some incorrect argument descriptions. Fixed
in both.
Note:
* Pass function to .off(), so that only that one is unbound
instead of any "resize" handler on the page (by other extensions
or gadgets or core)
* NB: ve.bind ($.proxy) preserves internal guid, so that $.Event
can find the bound function by the original reference.
* keydown has an anonymous function, should either moved to
prototype or namespaced, did latter for now, save enough and
better than destructive .off('keydown')
Change-Id: I9d05ef6e3e2461bdcf363232f7b0fbad5e24f506
We got lucky - the fact that our alien styling choice required phantom overlays had the nice side-effect of preventing the ability to focus the aliens. Therefore, as soon as we started ignoring IE to deliver nice alien handling for standards-compliant browsers, we inadvertently solved(?) the IE alien problem. I've touched up the styling to look nice in IE 9 (solid green phantoms) and IE 10 (stripes). Shield GIF switched to PNG because IE 10 renders the transparent GIF as solid red. Yeah, red.
Change-Id: I3bc69acba9ed883a823cdf722117b90966bc332b
This solves 2 issues:
1. Paste scrolls to the top of the editable box because we temporarily moved the focus to the paste container, and then moved it back. We solve this by saving/restoring the scroll position.
2. Scroll position adjusts vertically when pasting (using key repeat) because we handle pastes with a setTimeout and multiple paste jobs will pile up before they can be finished. We solve this by disallowing paste until we are done handling the previous one. In the case of key repeat this only is observable as slowing the repeat rate.
Thank you Christian for helping me solve this the old fashioned way - by sacrificing features you don't really need!
Change-Id: I75bcf9843b57cdff0db9b6dea62d66d4d76ac011
ve.dm.Document
* 2 of the 3 paths of getSlice still returned arrays instead of ve.dm.DocumentSlice objects
ve.ce.Surface
* Translate the range using the insertion transaction and truncate it, so the cursor ends up just after the pasted content
Change-Id: If7bae5e254ec84a847c1d3527f74d9c09c2d82b4
ve.ce.Surface
* Switched to using getSlice instead of getData in copy and paste handlers
* Added try/catch which attempts to build a transaction with the unbalanced data first, but falls back on the balanced data otherwise
ve.dm.*Node
* Added default style attributes (now used by ve.dm.NodeFactory)
ve.dm.Document
* Fixed bugs in fixupInsertions where parentType was being set with an object rather than a string
* Made use of getDataElement
* Added adoption capability so that inserting a</h1><p>b into <p>c[cursor]d</p> results in <p>ca</p><p>bd</p> rather than throwing an exception
* Renamed getBalancedData to getSlice, now retuning a ve.dm.DocumentSlice object
ve.dm.DocumentSlice
* Introduced new container for balanced data and a range of the original context - useful for copy/paste
ve.dm.NodeFactory
* Added getDataElement method, which uses default attributes to create a boilerplate version of a data element
ve.dm.Document.test
* Updated getBalancedData test to be a getSlice test
demos/ve/index, VisualEditor, test/index
* Added references to ve.dm.DocumentSlice
Change-Id: Id9269a29e51ca213508de8f155d3feec5e5b0774
The fix for bug 40339 supposedly modified when we emit contextChange events so that when the node changed, even if the context was the same, we consider it a context change (such as changing the heading level).
Unfortunately I was mentally absent when I wrote the patch and all it actually does it emit more select events.
Basically cb4877b0d0 - which does indeed fix the bug - doesn't do what it's commit message describes, but this fixes it.
Change-Id: I99d74f9ab0ddec15df41320389fe83de9b8b8d1e
* Decode titles we get from Parsoid
* Encode titles we give to Parsoid
* Preserve the original encoded title if nothing meaningful changed (a.k.a. do not normalize unless we must)
Change-Id: If5d22e88904d6b2c438caac403ac2d78d440b017
* Don't show at all if user isn't logged in
* Use "watch pages I create" and "watch pages I create" prefs
* If the user is already watching it, use that
Also updated relevant onMakeGlobalVariablesScript hook,
it was using old globals still, the hook has context as
of MediaWiki 1.19.
Change-Id: Ic3daf32505a745b3cccd0663a03bbf7f3885be84
Since model.change now starts the surfaceObserver, a problem manifested where the surfaceObserver was observing the $('#paste') element (used for capturing and sanitizing pasted content from external sources). Simply switching the order of the transaction and the documentNode focus fixed the problem.
Change-Id: I1b542b546d7f3d97e2e954ca4b51ca74232b2877
* Reusing deactivate method to recover from load error
* Made deactivate resilient to some properties not being set yet (so we can call it on load error)
* Restoring save dialog state after save error
Change-Id: I6a697dc6bddeebecf4e2ab26805bee9f3754c714
Logic taken from EditPage::getCopyrightWarning, but couldn't use
it directly because it doesn't give the message keys and wraps
the html.
Using the same logic and running the same hook, we'll get the same
message keys (and message parameters therefore) as EditPage would.
Also fixed these bugs (as they were more prominent now):
* Use Message::parse() instead of Message::plain()
* Set inLanguage properly instead of using the default
(EditPage is user-localised, including this message, just like
the rest of VE).
Fixes bug 42764: minoredit/watchthis should be in user-language.
Change-Id: I84fee641162cdeed290092e56fb0e1d2562d833d
The converter was misbehaving when handling <p>s inside <span>s. This
can't be expressed in the linmod, but it would try to anyway. <span><p>
would result in too many paragraph closing elements, leading to an
exception in ve.dm.Document complaining about unbalanced input.
<span>\n<p> would result in an exception in the converter itself while
trying to perform whitespace preservation on the newline.
This change makes the converter detect these scenarios and alienate the
offending node. So <span><p>Foo</p></span> converts to a wrapper
paragraph containing an alienInline whose HTML is "<p>Foo</p>" and which
is annotated with a TextStyleSpanAnnotation.
ve.dm.Converter.getDomFromData():
* Change the criteria for alienBlock vs alienInline
** Only infer from the node type if we're in wrapping mode AND we're at
the same level where the wrapping started (wrappingIsOurs). If the
latter isn't the case, we can't split the wrapper in the block case
because we're at the wrong level.
** Use alienInline not only if the branch is a content branch, but also
if there are active annotations. This catches e.g. <li><b><p>
(and generally <span><p> on the top level).
* Before converting a child element, check that the child isn't "bad".
Bad children are non-content children in content branches, and
non-content children encountered within a wrapper that we can't split.
Only good children are converted, and bad children are alienated (cue
Santa/Sinterklaas jokes).
* Add childIsContent and rename branchIsContent to branchHasContent
Change-Id: If420ae80ab0777424a9a5517335ef9d0170e87ae
Since the link is generated by a MediaWiki message and as far as
I know, the target attribute cannot be added in wikitext.
Solution is to add the target attribute via jQuery in the
save dialog.
Change-Id: I4b6cdee64e7f8e3acb28b21c32c58254d63a8daf
Get rid of ve.ce.Surface.locked (and isLocked, lock, unlock) and instead introduce ve.ce.Surface.renderingEnabled (and isRenderingEnabled, enableRendering, disableRendering) which names are way less confusing and more specific. Also add use of isRenderingEnabled to ve.ce.ContentBranchNode.
Change-Id: I72e9e8f8dfbf43784d7e616369acc3e9649c715a
Initializing range var in SurfaceObserver to use this.range instead of null to avoid passing wrong information to onContentChange.
Change-Id: I1d4e3fa2393166dad887077529351a479401bf4b
With the introduction of ActionFactory, we lost selection restoration. I've re-added it in the HistoryAction methods.
Change-Id: I018f9a9f85f5ce081e3b56c0f52aba24bc24cec5
ContentBranchNode shouldn't rerender on update, only on childUpdate.
When deleting across an inline node, update was emitted after the splice
had occurred in the DM but before the spice event was emitted that
caused the splice to happen in CE, leading to detached nodes and
associated sadness. See the bug for more details.
Change-Id: I2d44231b6e27efdb3f12967556cff174d9364d25
ApiVisualEditor
* Reverted some of I223235a6ea8b4178c50beeaaedb709b2de7cf0b5 turned out to be full of problems - the race condition is only relevant to getting the HTML
* Fixed check for $content to be false before it was defined
ve.init.mw.ViewPageTarget
* Reverted some more of I223235a6ea8b4178c50beeaaedb709b2de7cf0b5 - wgCurRevisionId is not equal to oldid, it's equal to $title->getLatestRevId() - this was causing lots of oldid problems
* Added use of restored message
* Made save button not locked when using oldid
* Customized save buttons depending on oldid
ve.init.mw.Target
* Reverted even more of I223235a6ea8b4178c50beeaaedb709b2de7cf0b5 - we don't want to keep a copy of the wgCurRevisionId at all, we just want the oldid if it was given
VisualEditor.i18n, VisualEditor
* Added restored notification and restore save button label messages
Change-Id: I8b30c2a153911f44643e369b7c6a9b89c0fb2c5b
* Fix 404 error for ve.ui.Icons-{raster,vector}.css
Follows-up 9563f08 / I840f72426f9a.
makeStaticLoader.php:
* Clean up old code.
* Error out early for missing module.
* Put i18n stuff in the right place
(some modules access ve.msg from the global scope to
assign status variables, for standalone on demos this was
failing due to wrong load order)
Change-Id: Idbff4c5136d567da747d9ae373cd2f6c3ee7fb1c
Rewrite VisualEditorMessagesModule:
* Replace copy-paste dump of user-css module with stuff for
VisualEditor (class commend and module::$origin).
* Remove duplication between getMessages and getScript.
* Actually implement getModifiedTime so that the comment in
getMessages() about cache invalidation is actually true
Fixes bug 42670: ext.visualEditor.specialMessages cache broken
ve.init:
* Implement addParsedMessages and getParsedMessage so that we
don't mix up plain messages with raw html messages (minoredit
was previously overloaded in mw.msg storage with a parsed html
message and retrieved though ve.msg, which is documented as
retuning plain text, not raw html). This is now separated into
a different method.
* Improved documentation of the other msg methods to emphasise
their differences
* Removed redundant code in attachSaveDialog() that was
(partially) already done in setupSaveDialog() and moved the
remaining bits into it as well. Checked all callers of these and
they are both only called from ViewPageTarget.prototype.onLoad
* Also implement them in the standalone platform implementation,
with the html escaper based on mw.html.escape
* Update init.platform.getMessage to use undefined instead of
discouraged 'if-in' statement.
* Add test suite.
demos/test:
* Re-run makeStaticLoader.php on test to add ve.init.Platform.test
* Re-run makeStaticLoader.php on demos and update i18n caller
to use ve.init.platform.addParsedMessages (also moved out of the
auto-generated block for easier updating)
Change-Id: I7f26b47e9467e850c08b9c217c4f1098590de109
HTML DOM has annoying behavior for <pre>s where .innerHTML eats the
first newline in a <pre>. Work around this by explicitly adding a
newline in the data->DOM converter if the <pre> already contained a
newline.
There is a separate bug in Parsoid that causes the newline to be lost
anyway, filed as bug 42666
Change-Id: Ia26cd4a4c61afbe439b0562deb7f24ee8b8147d7
DocumentNode element loses focus when the context is opened.
When clicking out of the context into window, polling error
occurs.
Change-Id: Ie8f8af763d221c59e47e8c240653f8b817c26f64
ve.ce.Surface
* Used getModel() as per TODO
* Simplified code by pre-calculating 2 statements that were being used 4 times each
* Re-structured logic so that simple insertion and deletion are only possible if next and previous have a range, triggering complex change otherwise
* Added some documentation
ve.ce.SurfaceObserver
* Added checks for whether rangy found a branch node within the document or not before accessing it's node via .data() and made it so we are only performing DOM > document range conversion if we did
* Removed some commented out code
Change-Id: Iaaf30a5b201710ab4235e775f18808a8d512f1f9
ve.IndentationAction
* Fix incompatibility with working with multiple nodes by using surface fragments
* Bug was caused by unindent causing rebuilding, which for all groups other than the first meant their nodes were detached and broken
ve.ListAction
* Employ unindent in a loop to remove all list levels
This is all still a bit hacked together, the use of surface fragments saved us this time, but we need to refactor this code. Badly. Next year.
Change-Id: Idddef35230b04d64cf8338d53bbab730fadec2fc
This will prevent inline alien phantoms from appearing while dragging. This was a usability enhancement identified by Inez/Christian.
Change-Id: Idf046db72e25875e899f5926ab7d50d2f514586b
Detecting contextChange events was making assumptions about the previous state, and causing a mess of problems.
Solution: detect contextChange events in a smarter way.
We also now emit contextChange event when moving to a different node. This helps fix other issues because it's possible for the selection to be the same, but the node at that range to change, and that's a context change for sure. Example would be changing the heading level.
Change-Id: I99d6fa94fae76aa940077abc9b5beacd38eb7b0b
This prevents memory waste when switching between read and visual editor tabs, which happens entirely on the client.
Change-Id: I31b50accac38d72a9367b9035504552dc0150104
Which for now is just "not when creating a new page". This is
already strictly enforced in the MediaWiki backend through EditPage.php, but not reflected in the Save dialog of VE yet.
Now the checkbox for Minor edit matches the logic for EditPage.
Change-Id: I9c659845feebb3e9bbf8e13ee67be27c6adb4321
Use mw.config wgCurRevisionId for oldie instead of uri query.
That way it also set on regular views, and as a bonus it the
normalised value (e.g. if on a page with oldid in query but the id
doesn't exist or is somehow invalid, it won't use it).
Centralise page existence logic in JS and rename Target.oldId to
Target.pageRevId (to further indicate that it is always set, not
just on oldId views. To detect an oldId view, do a boolean check
on value from currentUri.query.oldid directly).
In PHP Api, move oldid logic to execute() method instead of
locally from the getHTML call. That way it is always set, avoids
hitting this bug in other methods instead of just getHTML().
Since the mw.Target constructor now retrieves the ID from
mw.config directly, the second argument was removed.
Change-Id: I223235a6ea8b4178c50beeaaedb709b2de7cf0b5
Had to make the retrieval of the Save dialog html template
asynchronous due to mw.user.getRights being asynchronous.
Entire block indented, ignore whitespace changes.
Also:
* Fixed 2 cases where ve.msg value was interpreted as HTML
instead of adding a text node directly.
* Alphabetically sorted the dependencies (after adding
user.options and mediawiki.user).
* Removed redundant inline jshint comment, multistr is already
tolerated from the central .jshintrc file.
Change-Id: Ie09bb5c8bdbfbb3ec0d4983b74d0697b941153e0
ApiVisualEditor
* Including notices in response to parse actions
ve.init.mw.ViewPageTarget
* Added styles for editNoticeButton and editNotices
ve.init.mw.ViewPageTarget
* Added toolbarEditNoticeButton and toolbarEditNotices
* Combined toolbarEditNoticeButton and toolbarSaveButton setup
* Moved toolbar buttons setup to onLoad (it could vary per-parse now)
* Added tearDownToolbarButtons which fires on deactivate
* Renamed some instances of teardown to tearDown
* Added click handler for toolbarEditNoticeButton
* Added toolbarEditNotices setup method, called on load
* Made notices fade in and out, in by default on load if any
* Made notices hide when save dialog is opened
ve.init.mw.Target
* Added storing of notices on parse
icons, alert, ve.ui-Icons
* Added alert icon
VisualEditor.i18n, VisualEditor
* Added notices button message
Change-Id: I581bf5a005a9c18422f952d71064d17d0ba9b540
Context should be 'mw', not 'mw.msg'.
Also updated to using ve.bind instead and documented that ve.msg
cannot ve.bind because the reference 've.init.platform.getMessage'
does not exist yet at run time of the ve.js file.
Change-Id: I7eb692bdc4b63cc44fab118054d8eea05c2a71ff
When the content rendering stuff was moved to ve.ce.ContentBranchNode the onUpdate methods being used to update the DOM wrapper in ve.ce.HeadingNode was overlooked, so heading were not rendered on update anymore.
Change-Id: I994b8c43123c3cd02b9a550d5d7eac7d5052418e
* Permits longer page titles in suggestions without changing
the width of the dropdown.
* Addresses (Bug 40675)
Change-Id: Ie76a551970a040074b86c49bb44bda640ecd4845
The logic in ve.ui.LinkInspector.onUpdate was very flawed. This patch makes it so:
* When something happens, if there's an inspector open then so long as the selection hasn't changed the inspector is updated (such as the window being resized)
* If the selection does change, the inspector is closed
* If there's no inspector open, we try to show a menu of available inspectors
Change-Id: I859123a5fcd36bc2afb2e578f81f30a944c8583a
ve.ce.Surface
* Added ve.ce.Surface.adjustCursor, which replaces repetitive and buggy code that was handling left and right arrow key presses
* New method only affects the selection target, so it won't collapse the selection on you - this was what caused bug 42401
* Made hasSlugAtOffset() actually return a boolean
ve.dm.Document
* Fixed turn-around issue in ve.dm.Document.getRelativeOffset - if the offset is already valid and we can't move in the direction we want, we should just leave it be, not turn around
* Since this method was being used by ve.ce.Surface to correct the cursor position on arrow key presses, it was causing the strange cursor jumping when you pressed an arrow key while at the edge of a document
ve.dm.SurfaceFragment
* Fixed typo where getAnnotationRangeFromSelection was preserving selection direction, but checking the wrong properties
ve.dm.Document.test
* Added tests that verify turn-around issue is fixed
Change-Id: Iba55cfc3d531e7d1333b78c94912ff22179aace8
Allows suggest tool to open immediately and provide new page and
external link suggestions for link inspector.
Resolves (Bug 42341)
Change-Id: I79bc3e31033b5c38c3ed6ab23e601476cb17ba8f
ApiVisualEditor
* Added basetimestamp and starttimestamp to all methods where appropriate
* Added new serialize method which converts HTML to Wikitext
ve.init.mw.ViewPageTarget
* Added edit conflict handling
* Moved form value reading code into getSaveOptions method
* Prevented edit warning from appearing while submitting
ve.init.mw.Target
* Added serialize and submit methods
* Fixed some documentation
* Added support for baseTimeStamp and startTimeStamp
VisualEditor.i18n
* Added edit conflict confirmation box message
VisualEditor
* Included new edit conflict message to resource loader module
Change-Id: I002c5aa23704c1c46ef46fa1970a4254614b9eb1
ve.ce.Surface.handleDelete did not support inline elements. This patch resolves this by detecting them and using programatic delete instead of native browser delete.
Change-Id: I73215df88519450965be35d9e04cf4e621d1e90d
Moved annotation rendering from ce.Textnode into the new
ce.ContentBranchNode class. This allows us to render annotations that
span across multiple nodes.
* Add ce.ContentBranchNode, inheriting ce.BranchNode
* Make ce.{Paragraph,Heading,Preformatted}Node inherit ce.ContentBranchNode
* Made ce.ContentBranchNode render its child nodes with anntations,
using .getAnnotatedHtml() on the child nodes
* Put a default implementation for .getAnnotatedHtml() in ce.LeafNode
* Override this in ce.TextNode to do escaping and whitespace handling
* Removed rendering code from ce.TextNode (this.$ is now unused there)
* Removed ce.TextNode.onUpdate() and ce.BranchNode.clean(), now unneeded
* Have ce.BranchNode propagate update events from children, so
ce.ContentBranchNode can rerender when its children change
* Update tests, add test case for escaping of &<>'"
Change-Id: I4600e984b287c6ff9267f4281d2f09bab9e1ad95
* Remove the logic where we create a ve-edit button even though
we know there is no native ca-edit button (bug 42142).
This was previously in place to allow ve-editing a page while
restricting source editing, but this is no longer wanted.
* Implement new tabLayout mode "add", which adds a VE tab.
Previous default is now the "replace" mode, which replaces the
native "Edit" tab and creates a "Edit source" link.
Change-Id: I3fe29c52b743837c2e1d66f25ccdca6115b8bd25
Was broken both on the way in and on the way out.
* Move alien restoration (data->DOM) out of the main getDomFromData()
function and into getDomElementFromDataElement(). This means the
comment about District 9 is gone (sniff), but moving this here ensures
all code paths hit it (previously, it was assumed annotated nodes
could never be aliens).
* In the DOM->data converter, add annotation application to
getDataElementFromDomElement() (for content nodes) and createAlien()
(for aliens). Previously, these nodes would not get annotations.
** ve.AnnotationSet doesn't have a constructor that takes an array, we
should fix that.
Change-Id: I65f8e9a322111ca3af275bf9997b0b1e7ee93769
The transaction builder would step around inline content elements when
building annotation transactions. This is now fixed.
I also tweaked the processor to tolerate attempts to annotate inline
closings. This allows the builder to generate simpler transactions,
because it doesn't have to step around the closing.
Change-Id: I1e0d7f95b38bad1b35b3e125a53350d2d126a7de
This is cleaner than passing around the attributes separately, and it
allows us to access the annotations in dm.LeafNode as well.
Change-Id: Ie5b90988114835831cbe5cdccf63c7cd45719e31
* Added whitelist argument to setDomAttributes which allows filtering of attributes being set
* Added prefix argument to ve.dm.Node.getAttributes to allow extracting a subset of attributes by name prefix
* Added a whitelist to ve.ce.Node which was extracted from MediaWiki's Sanitizer class
* Replaced attribute copying code with a call to setDomAttributes using the whitelist argument, passing in attributes from a call to ve.dm.Node.getAttributes using the prefix argument
Also…
* Removed comment in constructor of ve.ce.Node, documentation for properties is usually in the getters/setters, and already was in this case
* Renamed ve.setDOMAttributes to ve.setDomAttributes
* Renamed ve.getDOMAttributes to ve.getDomAttributes
* Renamed ve.getDOMText to ve.getDomText
* Renamed ve.getDOMHash to ve.getDomHash
* Updated all callers of renamed methods
Change-Id: Id556172d5d18ea431044b9d402400e1f0e67a293
The contextChange event is fired when:
* Changes to insertion annotations
* Changes to which nodes are selected (start/end nodes have changed)
* Attributes have changed on any element (it's probably more expensive to detect if the changes are relevant than to just emit the event and let listeners do their thing)
This fixes most of the strange behavior with the toolbar not updating properly.
Change-Id: I5321d2e30bebd80987e0c779a9d8e061d8aa80bc
* Adjust offsets to correct positions before showing selection with them
* Throw an error inside of getNodeAndOffset if we can't find a match rather than mysteriously not retuning anything
Change-Id: Ia7347527e6466262e819f456404b32926fd95e34
This was because Firefox intially puts the selection before the first
paragraph, which translates to a model selection of (0,0). Typing with
the cursor at that position causes bad things to happen.
CE normally fixes up the selection when this happens, but it doesn't do
this automatically on initialization. So I added some code to ve.Surface
that causes this fixup to happen.
Change-Id: I0dcee3a29c1242c49ec30c743f1b69686fbb8436
ve.dm.SurfaceFragment
* Removed flawed implementation of word mode for expandRange method and made use of new getNearestWordBoundary method in the document model
ve.dm.Surface
* Got rid of useInsertionAnnotations, which allowed disabling and enabling of insertion annotations - this isn't needed anymore because it was just a dirty hack around the improper starting and stopping of surface observer that's now solved more elegantly by emitting lock and unlock before committing or rolling back transactions
* Get annotations from the first character of the selection if the selection is not collapsed
* Only emit annotationChange events if it really changed
ve.dm.Document
* Added getNearestWordBoundary method which performs the work behind the surface fragment expandRange word method
ve.ce.SurfaceObserver
* Allow using an initial selection to avoid the observer thinking the selection has changed just because it started out with null
* Only emit selectionChange event if there was a meaningful change
ve.ce.Surface
* (bug 42279) Only annotate characters if insertion annotations are not empty
* Remove manual locking and unlocking, this is now done inside the change method of surface model
* Provide an initial selection to surface observer when we clear it
* Remove enabling and disabling of insertionAnnotations, this isn't needed anymore
* Stop/start observer on key presses that execute actions as well as those that have no special handling
ve.ce.Document
* Make getNodeFromOffsetand getSlugAtOffset return null when given -1 as an offset
Change-Id: Ibf6b26de299e54ae8688a2653bf5d5538927f8c3
When working with a document containing only a slug in an empty paragraph, tree synchronization would break because it was trying to rebuild a non-existent text node.
This change makes the rebuild always occur on the outer range, rather than the inner range, which prevents absent text nodes from being asked to be rebuilt.
Thank you to Roan for debugging this for like 20 min.
Change-Id: I8c3dad921ace395f0694f77cec44305a680657fe
When editing a new page, or loading an empty page into the editor, the
converter generates a paragraph so the document isn't completely empty.
This paragraph is then unwrapped on the way out, potentially destroying
change markers and generally producing strange HTML output.
Mark this paragraph with generated=empty rather than generated=wrapper,
and only unwrap it on the way out if it's still empty. This means we
cleanly round-trip empty documents (and empty list items and the like),
but if the user enters text, we create a paragraph like we're supposed
to.
Change-Id: Id0241221a67b769445676b833b5741320d99ea5f
When alienating in wrapping mode, we need to look at the type of tag to
decide whether to create a wrapped alienInline, or to interrupt the
paragraph for an alienBlock.
This was being done just fine for the general alienation case
(unrecognized tag), but not for the special cases (mw:unrecognized,
about groups).
* Centralize the logic for ending a wrapper in stopWrapping()
* Move the wrapping-contingent block/inline detection logic into
createAlien()
* Simplify the terrible if statement to decide whether a future decision
requires us to stop wrapping. Instead, detect the cases in each code
path separately and call stopWrapping() as appropriate
* Add tests
Change-Id: I4054584ae05e7d5daa71edead3e6a6588cf5d3bb
Unfortunately support for Internet Explorer is currently insufficient in the CE module
which means we have to kill it for December; it will return once we've worked out a way
around various bugs in IE.
Change-Id: I0b44ae2c1d75ffe748a5139ca74dcda615e12a6a
Check for all node classes in getOffsetFromTextNode(), not just
branches and aliens (an entity is neither)
Render entities with contenteditable=false. Without this, selection was
still broken, because:
Foo|€Bar was really <p>Foo<span>|€</span>Bar</p> which maps correctly.
Foo€|Bar was really <p>Foo<span>€|</span>Bar</p> which maps to the same,
which is incorrect.
With cE=false, the cursor can't be inside the span, so we get:
Foo|€Bar is really <p>Foo|<span>€</span>Bar</p> which maps correctly.
Foo€|Bar is really <p>Foo<span>€</span>|Bar</p> which maps correctly.
Change-Id: Iaf603346590a9ad553c152565eb203136be7a399
ve.ui.Inspector
* Removed disabled state and interfaces - this isn't needed
* Renamed prepareSelection to onInitialize
* Using event emitter to run onInitialize, onOpen and onClose methods
* Left removal up to the child class to handle in the onClose method
* Replaced calls on context to close inspector to calling close directly
* Renamed prepareSelection stub to onInitialize
* Emitting initialize event from within the open method
* Added recursion guarding to close method
* Changed the close method's argument to be remove instead of accept - the more common case is to save changes, and the only time you wouldn't save changes is if you were to remove the annotation
* Moved focus restore to close method
ve.ui.Context
* Moved the majority of the code in openInspector and closeInspector to event handlers for onInspectorOpen and onInspectorClose
* Updated calls to closeInspector re: accept->remove argument change
ve.ui.LinkInspector
* Renamed prepareSelection to onInitialize and rewrote logic and documentation
* Removed unused onLocationInputChange method
* Moved restore focus (now it's in the inspector base class)
ve.dm.SurfaceFragment
* Added word mode for expandRange
ve.dm.Surface
* Added locking/unlocking while processing transactions - this was not an issue before because this was effectively being done manually throughout ce (which needs to be cleaned up) but once we started using the content action to insert content dm and ce started playing off each other and inserting in a loop - we already do this for undo/redo so it makes sense to do it here as well
ve.InspectorAction
* Updated arguments re: close method's accept->remove argument change
Change-Id: I38995d4101fda71bfb2e6fe516603507ce820937
<span typeof="mw:Entity"> tags are now correctly represented in the
model, and rendered in CE. There are still issues with cursor movement
etc. in CE.
Because the prioritization mechanism for annotations vs nodes is broken
in the current "node API", I had to hack two special cases for mw:Entity
into the converter. I also had to change the converter to ignore the
children of inline nodes (this was a legitimate bug, but had never come
up before).
Change-Id: Ib9f70437c58b4ca06aa09f7272bf51d9c41b18f2
* Make converter generate meta nodes with 'style': 'comment'
* Handle style==='comment' in MetaBlockNode toDOM converter
* Add some comments to the meta test case
** Update other tests accordingly
* Change getDomElementSummary() to actually assert presence of comment
nodes (specifically, all non-text child nodes)
Change-Id: Ieef9418f4c47df3541477d9420aa2ab8df6e3df1
MWInternalLinkAnnotation was normalizing spaces to underscores. This is
bad. Instead, we now do the following:
* Normalize underscores to spaces for display purposes
* Store the original title without underscore/space mangling
* If the user didn't change the title (display title === original title
with s/_/ /g), use the original title. Otherwise use the user's title
verbatim, without normalizing either underscores or spaces.
Also, per a conversation with Gabriel, we now only restore hrefPrefix
when we're also restoring origTitle, otherwise Parsoid will barf.
Change-Id: Ia74a493b2bce96c9345b60ed692eeb2e43ebceff
When you leave the inspector by changing the selection, we need to apply changes to the old selection.
ve.ui.Inspector
* Added initialSelection
* Change getMatchingAnnotations to use a given fragment rather than generating it's own
* Set initialSelection on open
ve.ui.Context
* Make hiding the context accept changes
ve.ui.LinkInspector
* Passing a fragment into getMatchingAnnotations now
* Using fragment API instead of actions API to control the range of the fragment
Change-Id: If6c8845285d87d0f144b15d50c38e192c797be59
When the link inspector is used to create a new annotation, the text is annotated with the default link target derived from the selected text. Then if the inspector is used to change that value, yet another transaction is processed when the inspector is closed.
To avoid having to press undo 2x, this change makes the inspector undo it's first change before applying the changed annotation.
This change also introduces insert, remove and select content actions.
Change-Id: I3e29189158fb01336d6b053bc2a8bda2a91a0a46
AnnotationAction and SurfaceFragment now use insertAnnotations.
ve.dm.Surface.test
* Removed test for annotate method (not needed anymore)
ve.dm.SurfaceFragment
* Now using getInsertionAnnotations method
* Added support for modifying insertion annotations when annotating a zero-length selection
ve.dm.Surface
* Moved in insertion annotations state from document model
* Added insertion annotation interface (enable, disable, areEnabled, get, set, add, and remove)
* Simplified handling of annotations on change
* Removed annotate method (not used anymore)
ve.dm.Document
* Removed insertion annotations (moved it to surface model)
ve.ce.Surface
* Cleaned up handleInsertion and changed it to use the insertion annotations interface on the surface model
ve.AnnotationAction
* Moved insertion annotation handling out of here since it's now included in the surface fragment
Change-Id: I047d656acf7fa1c63f726ca2b0801e1476f84f96
ve.AnnotationAction
* Added filter to the clearAll method to allow clearing all matching annotations only
ve.dm.Document
* Some variable renaming for consistency
ve.dm.SurfaceFragment
* Added truncateRange method
* Added annotation scope to expandRange method
* Added support for passing an annotation object into annotateContent method
* Switched to using name instead of type in annotateContent method to match the ve.dm.Annotation class
* Fixed logic in annotation mode of expandSelection so that expansion only takes place if the annotation is found
ve.ui.LinkInspector
* Moved most of the functionality elsewhere
* General reorganization
* Changed setOverlayPosition to accept 2 arguments instead of an object with 2 properties and renamed it to positionOverlayBelow
* Check for annotation object before extracting target information from it
* Initialize default target as empty string to avoid undefined being cast to a string and the default target becoming 'undefined'
icons.ai, inspector.png, inspector.svg
* Added generic inspector icon which will be used when a custom icon is not specified in future inspector subclasses
ve.ui.Inspector.Icons
* Added inspector icon
* Renamed clear icon to remove to match it's actual image
ve.ui.Context
* Greatly simplified the interface, reducing the number of methods by inlining a few things and combining others
* Now always listening to resize events on the window rather than only while document is focused
* Not listening to scroll events anymore, they used to affect the top/bottom positioning of the menu which we don't do anymore
* Lots of cleanup and reorganization
* No need to fallback to empty array since getInspectorsForAnnotations does so already
* Only consider fully-covered annotations for inspectors
ve.ui.Frame
* Simplified the constructor by introducing the createFrame method
* General cleanup
* Typo fixes
ve.ui.Inspector
* Generalized lots of functionality previously located in the link inspector class which will be useful to all inspectors (such as title, clear button, saving changes, etc.)
* Added setDisabled and isDisabled methods to manage CSS changes and avoid needing to check the CSS to determine the state of the inspector (storing state in the view is evil)
* Added getMatchingAnnotations method for convenience
* Added prepareSelection stub
* Lots of cleanup and documentation
* Type pattern is now defined in base class
* Added stubs for onOpen and onClose with documentation so that subclass authors know what these methods do
* Removed checks for onOpen or onClose methods since they are now noop stubs and are always there
* Added stub and removed checks for onRemove
* Made esc key close and accept - the illusion is supposed to be that the link changes are applied instantly, even though they are only updated when you close, so all closing except for when removing should apply changes - i.e. esc is now equal to back rather than being a special function that doesn't have an associated affordance
* Only consider fully-covered annotations when getting matching annotations
ve.ui.InspectorFactory
* Depending on type pattern now since it's always there
* Added getInspectorsForAnnotations method
* Return empty array if annotation set is empty
VisualEditor, VisualEditor.i18n
* Added default inspector message
Change-Id: I1cc008445bcbc8cba6754ca4b6ac0397575980d5
TransactionProcessor was using parentOuterRange without checking whether
it was present, so it was exploding for indexInNode results.
Now checking for parentOuterRange presence, and falling back to
nodeOuterRange when missing.
This fix causes inconsistencies with zero-length text nodes. We should
fix these eventually, but for now I've just made the unit tests
tolerant of zero-length-text-node deviations.
Change-Id: Id9eadd57a0d5fcbaf009c0781da0a03928aebb31
Editing the text of a list item results in a change marker on the
paragraph within that list item. However, that paragraph usually isn't
present in the HTML, so the converter unwraps it when converting back to
HTML, and the change markers are lost. Instead, transfer the change
markers to the <li>.
Change-Id: Id675075d19c08d69bc8e990174841dc393b749fc
If the mouse is moved too quickly, the phantoms have a tendency to stick. This change moves the event from phantom.mouseleave to surface.mousemove.
Change-Id: I2c7e7bdc838427d4355a6c0c13bafe3198636dbe
This changeset introduces new variable property of ve.ce.Node called "live", which stores information whether or not given node is attached to the live DOM. When the value of this property changes event "live" is called.
Change-Id: I6d0ce923c25ff2c4015914f367582c9a15e62c65
jQuery.css('float') returns different null values for Chrome and Firefox. This fix takes this into account and applies shields only to aliens and floated descendants.
Change-Id: I4c1db148043ee95991a17720dee8febad62c415a
Native contenteditable execCommands were being tried before the surface was attached to the DOM. This is necessary for disabling native contenteditable object editing and resizing.
Change-Id: Idff6a30432396726deb8a38356172380ea12fced