There's no point in hiding the WindowSet if we've already closed the
open window in it. In fact, there's no point in hiding a WindowSet
pretty much ever.
Change-Id: I49a02b5d255b266eb9e0a537cb64082eb0ad5e4b
ve.ui.MWReferenceDialog.prototype.teardown:
* Pass ranges rather than nodes to transaction builders
* Don't do a removal in insertion mode, we know the removal range
will be empty
ve.dm.Transaction.newFromDocumentInsertion:
* Correctly splice the edited internalItem into listData in the case
that newDoc isn't a document slice of doc
* Rename range to spliceItemRange for clarity
* Introduce spliceListNodeRange and set it to either newDoc's
listNodeRange or doc's depending on whether newDoc is a slice of doc
Bug: 57683
Change-Id: Iae7de7701ae86bed89b707038407243d82249e1a
Using display: none; on the inspectors WindowSet causes Firefox to
neglect to load CSS in the inspectors' iframes, which means the frame
never initializes and the inspector never opens.
Bug: 57568
Change-Id: Ia1a0ce78754fa1318a7d439abe1f0e2f86420e7a
Currently we assume getNearestContentOffset will give us something
sane however it can return -1 when there is no nearby content and so
an exception is thrown. In this case we have to create an empty
paragraph to place the cursor in.
Change-Id: Ic6c19da881e47ff6be45cdaa4b71bfcc1c654796
MW extensions are XML not HTML, so we shouldn't build them as XML
to prevent HTML specific rules being applied, such as <source>
always being self closing.
Bug: 54577
Change-Id: I84af4a29cd1c4ae4d1db4f70a4012a8ad0f98bf6
* changes:
Make autonumbered external links inspectable
Always remove the annotation when the remove button is clicked
Add abstract getAnnotation() method to AnnotationInspector
When the target of an autonumbered link is changed to a URL, it's kept
as an autonumbered link and its target is updated. When the target is
changed to a MediaWiki page, the autonumbered link is removed and
replaced with an internal link with the text set to the target.
So for instance, if you inspect [http://www.example.com] and change
its target to "Foo", the result will be [[Foo]].
The core of this commit adds support for inspecting nodes to
ve.ui.LinkInspector. This support should probably move into a
class in between AnnotationInspector and LinkInspector, perhaps
called HybridInspector or something, but I'm deferring that for now.
LinkInspector allows changes to inspected nodes to be reflected either
as attribute changes on the node, or by replacing the node with something
else. MWLinkInspector uses this feature to replace the autonumbered
external link node with an internal link annotation when the target is
set to an external link.
Bug: 53505
Change-Id: Icb404af84c24574438e4de3ef05bbd1993b593f7
When you inspect a link, then close the inspector immediately,
nothing should change. However, AnnotationInspector was comparing
the generated annotation and the existing annotation by hash, and so
would consider an annotation with htmlAttributes different from
one without. This meant that inspecting a Parsoid-generated link
and then closing the inspector would cause a transaction to be
processed that removes the htmlAttributes from the annotation.
I believe a similar issue also existed for annotations with attributes
like origTitle and hrefPrefix, although I didn't reproduce this.
The fix is to have AnnotationInspector compare annotations by the
hash of their comparableObjects, rather than their hashObjects.
Change-Id: I848ffc2b7e7b2c67754a0ece3af105ffafa837ec
Didn't bother to deduplicate blur-focus event pairs that occur when the
focus moves from the documentNode to the pasteTarget or vice versa
(this happens when switching between normal selection and FocusableNode
selection).
Change-Id: If1ccd2fbf11de956b6c2364ae81b9dc20a1bf409
Remove weird check that prevented a removal from happening if the
subclass's getAnnotation() method returned null.
This caused a bug where if you inspected a link, typed an invalid
link target (e.g. '|'), then clicked the remove button (trash can icon),
the inspector would close but the link wouldn't be removed.
However, if you typed something that was a valid link target (or didn't
touch the input at all), the remove button would work as expected.
Change-Id: Ib6efc2a5827b109c6b38185e6d89b7bb29b13a75
It was relied on, and all subclasses had one, but for some reason
it wasn't defined as an abstract method.
Change-Id: I6d48f8ee666bd339be87744840c6edb4abb56dbf
Otherwise the old save dialog will still be around if the user sets up
another surface (e.g. a second edit), but won't be attached to the DOM.
Bug: 57654
Change-Id: I23c10849a212534bdd0600637d8ad4fa3ebc4fb7
* changes:
Plain text paste with paste special
Use rare unicode characters for paste placeholders
Rich paste
Add fixUpInsertion to newFromDocumentReplace
This allows things outside of VisualEditor to style themselves
differently while the editor is active.
Bug: 57555
Change-Id: Ief6b5f53096dd5eeb43a72a7bb182a2c04ec97ca
This is a prerequisite to browser-based grapheme cluster handling, which
is needed so left/right cursoring and backspace behave as users expect.
modules/ve/ve.js
modules/ve/ce/ve.ce.Document.js
modules/ve/ce/ve.ce.js
* Revert cluster-aware splitting to trivial javascript code unit splitting
* Rewrite ve.splitClusters as a trivial compatibility method (remove soon)
* getClusterOffset/getByteOffset use unicodeJS.graphemebreak.splitClusters
modules/unicodejs/tools/unicodejs-properties.py
modules/unicodejs/unicodejs.graphemebreakproperties.js
modules/unicodejs/unicodejs.js
* Allow grapheme break tests to work with surrogate pairs
demos/ve/pages/minimal.html
demos/ve/pages/multibyte.html
demos/ve/pages/unicode.html
* replace file with more precise tests
modules/ve/test/ve.test.js
* Remove reference to grapheme-based splitting (which is no longer used)
* Correct typo
Bug: 53757
Bug: 51472
Bug: 51596
Bug: 51846
Change-Id: Ife34c87ebe40bc1689298b592eec5c0cdc2f7589
Register ctrl/cmd+shift+v as a trigger which sets a flag for the
next paste event.
When the paste special flag is set, modify the sanitizeData method
to strip all annotations, and any elements other than paragraphs.
Bug: 53781
Change-Id: If814e1786ffa805b52ab32f4a06f52da743fd9af
Allow pasting of rich (HTML) content.
ve.ce.Surface
* Use a sliced document clone for converting to DM HTML (copy)
* Add full context to pasteTarget before copying
* Add ve-pasteProtect class to spans to prevent them being dropped
* Implement external paste by converting HTML to data and inserting
with newFromDocumentInsertion
* Remove clipboard key placeholder after read so they aren't picked
up by rich paste. Hash no longer includes the placeholder.
* Detect the corruption of important spans and fallback to clipboard
data HTML if available.
ve.dm.LinearData
* Add clone method for copy
ve.dm.ElementLinearData
* Add compareUnannotated for use by context diffing.
* Add sanitize method for cleaning data according to a set of rules.
ve.dm.Transaction
* Add range parameter for inserting a range of a document only,
e.g. stripping the paste context.
ve.dm.Document
* Implement sliced document clone creation so that DM HTML
is generated correctly in onCopy
ve.dm.DocumentSlice
* Replaces LinearDataSlice. Now has two ranges for balanced data
and data with a full context.
ve.init.Target.js
* Define default, loose, paste rules (just remove aliens).
ve.init.mw.ViewPageTarget
* Define strict MW paste rules:
+ no links, spans, underlines
+ no images, divs, aliens
+ strip extra HTML attribues
ve.init.sa.Target, ve.init.mw.ViewPageTarget, ve.ui.Surface
* Pass through and store paste rules.
Bug: 41193
Bug: 48170
Bug: 50128
Bug: 53828
Change-Id: I38d63e31ee3e3ee11707e3fffed5174e1d633b42
There was a bug when you moved over an image with the arrow keys:
if your selection was on an image and you pressed an arrow key, the
selection would move but focus would remain with the paste target
rather than going back to the document node, which caused strange
symptoms (immobilizing the arrow keys and scrolling horizontally)
in Firefox.
Bug: 57600
Change-Id: Iaf6a49787dd2fd2f3f88abd0d1f5ae512fd3fd68
We had CSS that applied to our rendering of autonumbered links,
but not for raw <a rel="mw:ExtLink"></a> tags appearing in
generated content like templates.
Bug: 57420
Change-Id: Ic1585ecb1a133d16b7393ce0ce38a11b76cc2239
We were using it for the pop-out save dialog, but now that the save
dialog is real dialog, we don't need it any more.
Change-Id: I72697b5502d5f3fd19f2369a754a62d614af715b
Move the userPrefEnabled check out of isAvailable and instead check
it in-line with isAvailable for setting up the tabs with CSS, but
not for the veaction=edit function.
Bug: 55900
Change-Id: I23984e377ff3fc797e921546492b8c73a5101235
* Don't use setTimeout() within a change event, because change fires
after the text has already changed
* Don't use .$input.val(), use .getValue() instead
* Don't use .placeholder()
** Reaching into .$input is bad
** Any use of .placeholder() is TextInputWidget's responsibility
** All browsers we support also support placeholder natively
* Remove .editSummaryByteLimit from ViewPageTarget, unused
* Remove ve.bind() wrapping, we already have var saveDialog = this;
Change-Id: I380575fec8d02d1191bfc1f3f235b94c64cd23b6
The save dialog DOM is pretty big, so building it on demand
like every other dialog out there seems like a good idea.
Change-Id: I02077c3e45f01d3467d41616eb879bd1d608a82b
Each used their own implementation of building a form and submitting it.
The edit source one wasn't passing in the oldid, which caused edit
conflicts.
Also introduced a separation between form fields (for the action=edit UI)
and API options, building one from the other.
Bug: 56835
Change-Id: I38547b4ba1827f4028a2255109cba2a57cd59e8a
It looks like it also came from there originally, because it uses
this.pageExists which doesn't even exist in MWSaveDialog. This caused
all pages, even existing pages, to be watched when 'watchcreations'
was set.
This logic really belongs server-side, though.
Bug: 56206
Change-Id: Idf500383b27a93136dc0cfdd60a2e7b2607af95c
ve/ce/SurfaceObserver.js
* Do not setTimeout if frequency === null
demos/ve/eventLogger.html
* Standalone event logging script
ve/test/ce/imetests/*.js
* JSON event logs for various tests/browsers/IMEs
ve/test/ce/ve.ce.test.js
* Add an IME test
VisualEditor.hooks.php
* Add test files
Change-Id: I50e89d5a289f3fcb4fe2a6835a2ec96fb497242c
* modules/ve/test/ce/ve.ce.TestRunner.js
Class to interact with the CE Surface and document in tests
* modules/ve/ve.EventSequencer.js
Wrap setTimeout/clearTimeout calls (for easy replacement in tests)
Change-Id: I2e2407e2b169ae77237c87bf8857b3026cc7efce
Move generation of initial edit summary from setupSaveDialog() to
restoreEditSection().
This allows us to get rid of the properties tracking whether both
halves of the edit section handling had happened, because they're
now in the same method.
Moving setupSaveDialog() down so it runs after restoreEditSection();
this is needed for the communication via this.initialEditSummary
to work correctly.
Change-Id: I06a9c5cf5c752acea8a2ac25d0ffb6ac61cfe986
Add prepareCacheKey() which submits HTML for serialization and saves
the resulting cache key, and tryWithPreparedCacheKey() which uses that
cache key (if available; if pending, it waits for it) for API requests.
Implemented save(), serialize() and showChanges() in terms of
tryWithPreparedCacheKey().
When opening the save dialog, run the conversion, cache it, and fire
off a prepareCacheKey(). Then use the cached conversion for save/diff/
serialize. This means we don't convert multiple times, and it causes
the prepared wikitext to be used.
Bug: 55979
Bug: 56011
Change-Id: I1d56fe88d312e9810a57d56a285ccdf4f1facf42
* parameter.svg had no opacity set
* replace.svg had a document opacity of 80% in addition to the normal 75%
* re-rendered parameter.png (syntaxhighlight doesn't have png's yet)
Change-Id: I9c990fefaf4f5a7536b884b92523408146d7b2c7
initialize() is currently called synchronously, but once the CSS
transplantation code is fixed and it goes back to being async, that'll
cause problems.
* Add this.setupDeferred and use it to defer setupCheckboxes() until
after initialization
* Move code populating the edit summary from ViewPageTarget into
MWSaveDialog and use .setValue() rather than manipulating the
TextInputWidget's DOM. Defer this until after init as well
* Move clearing of the diff from ViewPageTarget into MWSaveDialog,
and don't connect it to the transact event at startup, only when
we've actually shown a diff
* Remove swapPanel( 'save' ) from ViewPageTarget, instead do this
on setup in the dialog itself
Bonus:
* Document events
* Get rid of onFooButtonClick handlers in favor of array syntax
Change-Id: Idcdae5e013340f4519db4387bab507e714d47941
We can't get the directionality from the focused node if there isn't one.
This doesn't add any logic to determine the directionality in creation
mode, filed https://bugzilla.wikimedia.org/show_bug.cgi?id=57421 for that.
Change-Id: I3ff8d48f19c7beef5e24b55712a26d86efa5812a
In order to do this we have to separate out the removal
operation from NDFR, so it becomes newFromDocumentInsertion
(again, although actually, for the first time). As NFDI is
an insertion we can just run fixUpInsertion on the data
part of it.
In order for the removal operation to be a proper removal
we have to allow metadata removal (the default is to merge it).
Change-Id: I16d575b61b9796e7e889f2c27cfe02b4a40b7639
This fixes some of the problems with pasting references.
It's a bit overzealous in that references get renumbered even when
replacing, which is unnecessary but doesn't actually have any
noticeable effect.
Unfortunately, the internal list state depends so much on the converter
having run that we now need to add yet another hack, to set the counter
to the appropriate value.
Change-Id: I3c6514ce600af4f4c037f419554d34b5a5c86a63
* Use 'this' instead of 'viewPage' in setupSaveDialog()
* Unwrap unnecessary .each() in restoreEditSection()
Change-Id: I45d0c9714d59e195d0c4413ed3dbe9cbabe45e9d
* Fix invalid @param name (mixup of type and param name).
* Fix incorrect reliance on inferred name for ve.Range.
@class uses the below function to guess its name, however
if @property is encountered, the @class block ends. Thus
it was indexed as a nameless class.
* Separate @property definitions because combining them like
that doesn't work (it silently ignored everything after the
first "from" property).
Also:
* Add some missing @static to static methods in ve.Range.
* Remove a few redundant @method while at it.
Change-Id: I8357c30711a4830af0b68b18350352c457a607f3
Us grouping the inheritable static properties that way is an
implementation detail that is polluting the index and makes
it harder to refer to individual identifiers.
It also causes problems under JSDuck 5 because that version is
more strict about defining properties (Foo.static.bar) of which
the parent is not defined in the index (Foo.static), we'd have
to add a sea of `@static @property {Object} this.static` all
over the place. Might as well hide this implementation detail
and just consider them static properties (just like we already
do for "private" properties).
Change-Id: Ibf2ebf7752aabc2b75b6ac6fa00e2284a181a600
setValue() doesn't do anything if this.value === value, but with
sanitization it's possible for that to be true while the value in
the DOM is out of sync and needs to be changed.
The fix is to check for this.value changing and the DOM changing
separately.
Change-Id: I5f571445f5729f5477902c155a4ee9588b7194a8
Previously we had a defaultSortKeyChanged value that lied - it was
possible for the value to be changed A -> B -> A by the user mid-
edit. However, the meta dialog assumed that defaultSortKeyChanged
wasn't lying, so blindly changed the meta item to the new value,
causing an unnecessary meta change if the user had done a no-op.
Now the value is renamed to defaultSortKeyTouched, and we actually
detect for content changes, and only change the meta item if a
change is actually needed (be that a removal, a replacement, or an
insertion).
Change-Id: I13022090bd7561a460a1151013e2b7d2a029f4dd
Also encourage callers to pass plain objects unless they know what
they're doing; it's almost always wrong to pass in a MetaItem.
Change-Id: I8e8ef8ac7f77ec9f929d797e467b9c9d1140d721
This was a regression that occurred when the toolbar was refactored
recently. The correct and previous behavior was if the cursor is in a
location where the context would show an inspector tool, that inspector
tool should be active in the toolbar.
Change-Id: I8ac2b1bd21b843db30e3e9f951702378007e139a
Otherwise you get rendering issues when you resizing adjacent
resizable nodes and you drag over the other node.
Change-Id: Ie70833fa6ae38879b70a19e8d7ecec13a1d54e92
As of 46f40dc, we've split the VisualEditor API backend and the
part containing the parsefragment method no longer needs
an edit token.
This gets rid of the warning that started appearing after 46f40dc:
{
"warnings":{"main":{"*":"Unrecognized parameter: 'token'"}},
"visualeditor":{"result":"success","content":"<p>foo\n</p>"}
}
Change-Id: I36f79fa8ae48cdbec1b3506953418561ef2ff828
The generation promise can get resolved (e.g. AJAX request can complete)
after the node has been detached. In that case accessing this.model.doc
will fail, so check for this in doneGenerating().
Also attempt to abort the pending promise on teardown.
Bug: 56649
Change-Id: Ia55f1c2c8dc3a3619c0b50795e50fcae4bc6471f
Previously was failing for two reasons:
1. FF requires the form to be attached before submitting
2. options.watch failed because of FF's annoying Object.prototype.watch
Bug: 56767
Change-Id: I7b3d349f057f5b87f823ce788b4143f817af5303
Syntax highlight editor shouldn't rely on GUI language directionality
but always allow for LTR text editing.
Bug: 56780
Change-Id: Iae7f9eee20ffb9a003830503865458918f5e1df3
Changes:
* Cleanup the window API to use more consistent and intuitive methods - we
now use initialize/setup/teardown instead of
initialize/onSetup/onOpen/onClose as methods which are overridden, and
use open/close methods to control the window
* Change events around to have opening/open and closing/close events which
act as before/after points during the opening/closing process
* Make WindowSet and Context respond to windows being opened, rather than
opening them directly
* Fix a LinkInspector creation mode bug where the initial text doesn't get
reset
* Move inspector, a VisualEditor concept, back to VE
* Cleanup naming of SurfaceDialog, SurfaceToolbar, etc. to use shorter
names, they were given Surface* names when the generic ones were also in
VE, but now the generic ones are in OO, so they can return to their
original names
Change-Id: I82c4fed8bcb3fb5630938c8bc4dd9b2d5f1a8c1d
In general, the direction of the MWExtensionInspector textarea
should be dependent on the directionality of the node it is editing.
The only exceptions are <hiero> and <math> that need to have their
textarea LTR always; these two inspectors' directionality definition
is overridden in their onOpen() method.
Bug: 56779
Change-Id: Iac5c1c3bf2c61b9fa36c9588c1734c91ca4305c4
Underline is particularly important as CE will apply underline
formatting automatically when you press Ctrl+U but the
SurfaceObserver will not notice it, leading to inconsistency
between the view and the model.
For sub/superscript I've used the Google Docs key mappings as these
appear to have the fewest conflicts with existing browser shortcuts
and there isn't much consistency between desktop clients anyway
(Word and Open/LibreOffice use completely different shortcuts).
Bonus: reordered command lists to be consistent with UI layout.
Change-Id: I92998e42f9bcfb932d44e8f483811efd538e5981
Renamed events:
* performance.domLoad --> performance.system.domLoad
* performance.domSave --> performance.system.domSave
New events:
* performance.system.activation: total load time
* performance.system.domDiff: timing of paction=diff; like .domSave
* performance.system.domSerialize: timing of paction=serialize; like .domSave
* behavior.lastTransactionTillSaveDialogOpen: time from last transaction
until user opened save dialog
* behavior.saveDialogOpenTillSave: time from save dialog opening to user
clicking save
* behavior.saveDialogOpenTillReview: time from save dialog opening to user
clicking review (skipped when a cached diff is shown)
* behavior.saveDialogClose: when user closes save dialog; duration is time
* performance.user.saveComplete: time from user clicking save to successful
save completion; 'retries' indicates # of badtoken retries
* performance.user.saveError.*: time from user clicking save to failure;
'retries' indicates # of badtoken retries
** performance.user.saveError.abusefilter
** performance.user.saveError.badtoken: token was bad and we prompted the user
** performance.user.saveError.captcha
** performance.user.saveError.editconflict
** performance.user.saveError.empty
** performance.user.saveError.spamblacklist
** performance.user.saveError.unknown
* performance.user.reviewComplete: time from user clicking review to diff showing
* performance.user.reviewError: time from user clicking review to diff failure
since dialog was opened
Change-Id: I9815fa637d34c766c163e181d2f9527d3f32a7c3
When the editor is focused, the selection goes back to the start of
the document. This was remedied in the .focus() method, but not in
response to native focus events, so when external code blurred then
refocused the editor, the selection would move to the top.
This broke section editing on wikis where ULS is installed: the
selection would be initialized at the start of the section, but then
ULS would load and blur the documentNode (by focusing the pasteTarget)
and then focus it again, so the selection would move to the top.
Instead of restoring the selection only in .focus(), restore it in
response to focus events on the documentNode. When this is done,
saving and restoring the scrollTop is no longer needed.
Bug: 56651
Change-Id: I14700174ee092f9b208215d31a7d1871078a89bf
The resizing handles under ResizableNode are created in the location of the image
but if the page is edited and the image moves relative to the document, the handles
remained where the image was previously and not where its updated location is at.
This code fixes that bug by changing the CE event listening to the model's 'transact'
instead of 'history', and clears the cached offset when a 'transact' event happens.
Change-Id: Id0e4296dd89b24839ba68a534ca77d73c23b7434
When the ListToolGroup in the toolbar (the "More" section) is scrolled
down such that the top tool is partly obscured, and you hover over the
bottom half of the "More" button, the top tool displays a hover effect
and using the scroll wheel will scroll the list rather than the page.
This is because the list has a box-shadow that's 1em tall, and the
height of the "More" button is 2em. And in Chrome, pointer events
"work" even in the box-shadow area. Roan reported the Chrome bug at
https://code.google.com/p/chromium/issues/detail?id=314291
This change works around the bug by making the tools in the list
inline-block instead of block; for some reason the bug only affects
block elements.
Change-Id: I4ea3f41c91d0ff5d5cc150fe8acc3427f0ab5f3a
Some 've-ui-toolbar-bar' classes hadn't been converted to OO.ui so the
toolbar had no border. Also removed a useless rule in mw.ViewPageTarget.css.
SA platform didn't override OO.ui.msg to use the ve.msg so no messages
were getting through.
Change-Id: Ieb5bc3c98d1c435ec194b201b517a688cd9b02b9
* Our metadata insertions now need to be the same length as the data
insertion, not one more, so:
** Remove the +1 in the listMetadata splice
** Shorten the metadata variable by dropping the merging of the
metadata right before and right after the internal list; it was
also including the metadata right after the internal list twice
*** We still need to deal with this in some way though, left a TODO
** Fix the metadata insertion test for these changes
* Fix null reference keys in the test data; we made all references
keyed a while ago, but this test data was never updated for that
** The remapping of reference data doesn't remap auto/N keys yet,
left a FIXME for that
Change-Id: I8ef4e6ee7c1808574d81d0b83294848afd400cd7
Stop using this.$.frame.dir - a horrible hack made of duct tape
and bubble gum.
Or perhaps rather, masking tape and post-it-notes...
Change-Id: I53690e4485974b95edbdd255c0b96c2f639c5261
Objectives:
* Rename this.$ to this.$element
* Rename this.$$ to this.$
* Get rid of the need to use this.frame.$$
* Rename OO.ui.Element.get$$ to OO.ui.Element.getJQuery
Changes: (using Sublime Text regex patterns)
* Replace "get$$" with "getJQuery"
* Replace "\.(\$)([^\$a-zA-Z])" with ".$element$2"
* Replace "\.(\$\$)" with ".$"
* Replace "'$$'" with "'$'"
* Set this.$ to null in constructor of OO.ui.Window
* Set this.$ to this.frame.$ in initialize method of OO.ui.Window
* Replace "\.(frame.\$)([^\$a-zA-Z])" with ".\$$2"
Bonus:
* Use this.$() in a bunch of places where $() was erroneously used
Change-Id: If3d870124ab8d10f8223532cda95c2b2b075db94
Replaced uses of extendObject with $.extend . Replaced the one use of
OO.ui.indexOf with Array.prototype.indexOf because that's what
everything else was already using.
Change-Id: I63f40989057b8065ec977efafbf68d6e22c8e679
By serialising the current DOM, and injecting it into a form we can
end up in the source editor with our VE changes converted.
Bug: 50687
Change-Id: Iafcc02a737d9c6c3a59dce1caff130d47ca25650
Calculate and store the two inner whitespace values of the body in the
dm.Document. When converting back, make sure the first/last nodes
pre/post outer whitespace matches the inner left/right whitespace
of the body.
Bug: 54964
Change-Id: I45f1ffd63669f25a6cae878400bfe21719ed58ee
Also removed comment in ui.MWTransclusionDialog that was
copied from dm.MWTemplateSpecModel.
Bug: 50888
Change-Id: I9dcfef3ae65fe716bae91f703f9169171448797a
* Method is private.
* Code example and bullet list were rendered badly due to a
single line break having no meaning in markdown (this makes
80-char linebreaks easier). Need an empty line to separate block
elements (e.g. paragraph from list, and list from next paragraph).
* Fixed #register reference to be a doc link instead. The invocation
parenthesis look confusing (imply it needs no arguments).
Change-Id: Ib6cab4599ec3e310ec4355bdb1d60b1e53429c69
Objectives:
* Hamburger menu in actions area of toolbar
* Add tools that open specific pages in the meta dialog
* Fix support for using setPage in ve.ui.PagedOutlineLayout
* Allow passing setup config objects through window open calls
* Add dialog action, similar to inspector action
* Fix incorrect or missing documentation
Change-Id: I2d2c9b87554fb2a0c90ed6944a58b38a37efa712
Just override OO.ui.Tool.prototype.getTitle. The default implementation
uses the same static property as before.
Change-Id: I80fd95142cafac0e136cfe3031c16c371625b469
This allows other content to be added without it being nested inside an
<a> which results undesired visual and functional effects.
Change-Id: I667878fe4ae682712094a61bb4b411ac5fb999c7
Changes:
* Pass toolGroup into tools instead of toolbar
* Split tool labels into title and accel
* Make toolbars provide accelerator labels
* Remove getLabelText method since it's not being used and is likely not useful
* Make tools update their own labels
* Only show accelerator information for triggers that are active in the surface
* Make surface toolbars listen to commands being added and update tools accordingly
* Introduce command object to encapsulate command info
Change-Id: Ieac4bfa63b63ac0a9dee154af3007a33b4d447ff
* Move and rename generic parts of ve.ui to OO.ui
* We now have a UI test suite because ve.Element (outside ve.ui)
is now part of oojs-ui, so it needs a test suite.
* Added to the MW test run (just like we do for unicodejs).
* Updated csslint config (also added ve-mw and syntaxhighlight
which were missing).
oojs-ui still depends on the TriggerRegistry in VE, this is addressed
in a follow-up commit.
Change-Id: Iec147155c1ddf20b73a4d15d87b8742207032312
Make every module that was formerly part of the experimental module its own
Beta Feature. For now, all of them are commented out except for formulæ editing
(mwmath). The "experimental" Beta Feature bucket is no more, but the preference
remains so that it can be set to both true and hidden on MediaWiki.org to let
all the different experimental flags.
The feature icons, previous mis-named "logo" and mis-identified as "screenshots"
are now renamed. One for the mwmath Beta Feature has been added (the rest need
creating before those can be enabled). The i18n descriptions now each identify
that the feature is an experimental one, and that caution is needed.
Change-Id: I28862f3e62f5c78aca33f11265aced1db67f4725
* changes:
Get rid of dmRendering hack in ve.ce.MWInternalLinkAnnotation
Render resolved URLs for href and src attributes in CE
Give ce.Annotations a reference to their ce.ContentBranchNode
Track the original HTMLDocument in ve.dm.Document
Create CE nodes and annotations with the correct $$
Add ve.resolveUrl for URL resolution
Don't render href as src in MWBlockImageNode
Rename 'html' to 'body' in converter tests
Centralize href computation in getHref(). Because getHref() is provided
by the generic LinkAnnotation class, the subclass implementation is
now simpler.
Bug: 51487
Change-Id: Ia6ca85bc84b4f4453b572285836adb631e8d0683
URLs are resolved according to the <base> URL from the Parsoid DOM.
For instance, a link can have its href set to '../Foo' in the DM, and
the target will show up as '../Foo' in the link inspector, but the CE
rendering will be <a href="http://localhost/Foo"> (assuming Parsoid sent
<base href="http://localhost/wiki/Bar">).
Bug: 48915
Change-Id: I919135eb758c82361525078f276ca193dc4c4820
This gives them a way to reach the dm.Document, which is needed
for ce.Annotations to do URL resolution.
Change-Id: Ia18bd8fc3510ad1b627644cd2c6ebcf148254e05
Add it as an optional parameter to the constructor, and create a new
one if omitted.
This is going to be used to resolve URLs according to the right <base>,
but really that's a hack and we should come up with a better way to
track metadata from the <head>.
Change-Id: I49dfc81ff793d73e08a20e502d681a15613d23f7
Most of CE wasn't passing through $$ at all. Also fix CE tests that
weren't passing the required surface parameter to the ce.Document
constructor.
Change-Id: Ia234f174050f4b2666ec20e8acc24c6aa4305202
Because that's what it is now since 'head' was added. Also removed
the wrapping <body> tag (now added by the test runner) and renamed
normalizedHtml to normalizedBody.
Change-Id: I5624ae076c5e661d2789e499cd28e8282c885409
This is done by using the computed property value rather than the
literal attribute value when rendering href and src attributes.
Helpfully, this provides perfect URL resolution natively in the browser,
which means the document's <base> is respected and all that good stuff.
For GeneratedContentNodes, we also need to find all DOM elements inside
the rendered DOM that have href or src attributes and resolve those.
This is done in the new getRenderedDomElements() function, which the
existing cleanup steps (remove <link>/<meta>/<style>, clone for
correct document) were moved into.
In order to make sure that the computed values are always computed
correctly, we need to make sure that in cases where HTML strings
in data-mw are parsed, they're parsed in the context of the correct
document so the correct <base> is applied.
We still need to solve this problem for models that actually store and
edit an href or src as an attribute. I'll post more about that on
bug 48915.
Bug: 48915
Change-Id: Iaccb9e3fc05cd151a0f5e632c8d3bd3568735309
ContentBranchNode renderContents changes the browser selection, so we
need to change it back.
ve.ce.ContentBranchNode.js
* When rerendering, set a flag on ve.ce.Surface
ve.ce.Surface.js
* On model documentUpdate, reapply selection if flag set
Change-Id: Ib8a168e6ec674b9d8021423f21f7acca75c2fd7c
The SurfaceObserver lock guarded against setTimeout calls, but the lock
was only ever used synchronously.
Remove 'lock' and 'unlock' events. Instead, re-sync the SurfaceObserver
by listening to the 'documentUpdate' and 'select' events.
Signed-off-by: Roan Kattouw <roan.kattouw@gmail.com>
Change-Id: Ib15c39f3d25677da70625581b3b2765ae66994b4
...or really changeInternal(), so we can avoid adding undo transactions
to the undo stack.
Also get rid of the pattern where undo() and redo() return a selection
which the caller then has to restore, and instead just restore the
selection.
Bug: 53224
Change-Id: If5a3b4d4162e9f0713ee9cd26e79a66efe52770f
* Replace surface 'transact' event with 'documentUpdate' event
* Have surface listen for all document transactions and update selection
as appropriate (as well as emitting 'documentUpdate')
* Implement change() in terms of setSelection()
** Queue 'contextChange' events so contextChange is only emitted once
** Use this.transacting flag to prevent setSelection() (which is called
because the model emits transact events) from doing too much
** Behavioral change: lock/unlock now emitted separately for
transaction and selection changes
Change-Id: I44425d260ec70758f99d13f99e41f5c993d260c2
ve.dm.Surface.js:
* Stop emitting 'change' and remove its event documentation
ve.ce.Surface.js:
* Listen to 'select' instead of 'change'
* Perform a CE surface update after model-based keydown handling
ve.dm.Surface.test.js:
* Stop asserting that 'change' is emitted
Change-Id: I8f16289493e835d890709c6dfe093d04c18522b6
Binding ve.init.mw.Target#onLoad and the anonymous function which calls ve#track
with timing data to the resolution of the same deferred makes the timing
measurement sensitive to how long it takes ve.init.mw.Target#onLoad to yield,
which in turns depends on whether the requisite ResourceLoader modules for
setting up the editing surface are ready. This muddles the definition of what
we're actually measuring, making it dependent on a race condition.
This patch moves the tracking call to a filter function through which the jqXHR
deferred is threaded. This ensures that the 'duration' datapoint on the domSave
and domLoad events captures just the time spent talking with the API.
Change-Id: I6e162014a4043d4ff9422131ae87fb25d0ab4c29
Math, hiero, language and alienextension are now each in their own
module. Kept the experimental module for backwards compatibility,
it just has all of its constituent modules as dependencies.
MWExperimentalTool.js was split up, and ExperimentalTool.js was
renamed to LanguageInspectorTool.js.
Change-Id: I63b49dfbdb59dc9a494049553cc0c01e89e48826
Because QUnit's inline diff is terrible for large diffs,
especially when there are block whitespaces changes.
Change-Id: I786fb981b02777ede38c4bee261f9e32f8f908ed
Instead, listen to 'select', or to 'transact' on the dm.Document.
This commit only fixes uses outside of the dm/ce.Surface ecosystem.
ce.Surface still listens to 'change'.
ve.init.mw.ViewPageTarget.js:
* Rename onSurfaceModelTransact to clearSaveDialogDiff and bind it to
the document's transact event instead
* Rename onSurfaceModelChange to checkForWikitextWarning and bind it
to the surface's transact event. This is needed because the function
inspects the surface's selection, which isn't yet in a consistent
state when the document's transact event fires
ve.ui.MWReferenceDialog.js:
* Rename onSurfaceChange to onDocumentTransact and rebind accordingly
ve.ce.ProtectedNode.js:
* Get rid of onSurfaceModelChange
* Instead, bind positionPhantoms to the document's transact event
directly, and only bind it while phantoms are visible
ve.ui.Context.js:
* Rename onChange to onModelSelect and rebind accordingly
* Rename afterChange to afterModelSelect
* Drop check for undefined selection, no longer needed now that we're
listening to a finer-grained event
ve.ce.Surface.test.js:
* Listen to 'select' instead of 'change'
Change-Id: Ifeb1a1fc5427696f2aae5441d4b54dde366793e0
It was previously emitted before the selection was updated and with the
old selection as a parameter. Instead, emit it afterwards, and make sure
it's emitted even if the selection changes because it was translated
for a transaction.
Also correct its event documentation, which seems to have been copied
from a UI class somewhere.
Change-Id: I521eff0095959572587c0ecffd24dbf322e12d82
Move selection change handling (closing the popup if open, and updating
the context toolbar) to .afterChange(). Every time .onChange() detects
a selection change, it schedules a call to afterChange(). These calls
are batched so that multiple selection changes in the same tick cause
afterChange() to be called only once.
Deferring these updates causes them to no longer occur while a 'change'
event is being emitted. This means that if an inspectors' close handler
calls .change(), that call is now no longer nested inside another
.change() call and doesn't run afoul of any render locks set by the
caller of the outer .change().
Bug: 54675
Change-Id: Iae2f41a83b5d64251a54e42303100e84a5c25561
AnnotationInspector changes the selection from both its open and close
handlers, which can cause recursive calls to .hide() and .update()
Change-Id: Ic334f9b8b335fe1aaac2dc98dc6ea9fd9d5707ff
Update checks if there's actually a context menu to show. We also need
to pass through the parameters for show.
This was causing the last-shown context menu to appears after resizing
an inline image (which has no context menu).
Change-Id: I8f46f71e2fba6896fe10054f0d2a679c6f23eb9c
Both the resize handles and the size label position themselves
using $resizable's relative offset, so we can optimise by
caching that result.
Change-Id: Ic225b15cfcece8d5c2e782e1e667d854f805c6fb
Because it can change. Currently the resize label is not
positioned correctly if you use three of four resize handles.
Change-Id: I1a28bc57fda1097c94047fd7690ad8d403cdd478
Instead use OO directly. Also remove ve.createObject, which is
unused now that ve.Registry and ve.Factory have been moved to oojs.
Change-Id: I3470b6660107ddd0bdf4a43c50d191a1bb1cc4d8
Instead of using @emits in both, use our custom @fires in
production (JSDuck 4), and in the future it'll just naturally
use the native one.
This way we can also index oojs without issues, which seems to
have started using @fires already.
Change-Id: I7c3b56dd112626d57fa87ab995d205fb782a0149
If there was an error loading the HTML from Parsoid, ViewPageTarget
would try to tear down the save dialog, which caused a crash because
the save dialog doesn't exist yet at that point.
Change-Id: Ia50756a19cb775be96b90e87b642eb2a38f254ce
The previous recursion "guard" relied on the recursion to occur for
the function to work correctly, which was very confusing. Additionally,
it didn't actually work: if the inspector's onClose handler changed
the selection (which is common), .hide() would recurse and the recursion
guard didn't catch this (inspector wasn't undefined yet). Fortunately
all that did was call .close() on the inspector again, which was caught
by .close()'s own recursion guard.
Instead, simply use this.hiding as a recursion guard, and refactor the
function so it doesn't do two different things depending on whether it's
expecting recursion or not.
Change-Id: I09eb9229530468ee319ca53b730784a3f632375d
Since I0f0a826c in Parsoid, numbered external links are now empty
<a rel="mw:ExtLink"></a> tags. This means we have to put in a node type
for them to prevent them from being considered empty annotations and
getting converted to alienMeta.
MWNumberedExternalLinkNode is protected and focusable to avoid making
the link text (which isn't editable) clickable. It isn't inspectable
yet, we need to work on that.
Bug: 53505
Change-Id: I83f69695f3974089e51a84e799f31ab6ed879e05
Part of the ongoing effort to expand the amount of languages that can be
highlighted by syntaxhighlight module to match that of SyntaxHighlight
GeSHi extension.
The module now separates language names with their file names.
Change-Id: Iaf907ebeadc9432719a45f4e9e8d580bb32ca668
SelectWidget would refuse to select unselectable items on mousedown or
mousemove, but would happily do so on mouseup. This meant unselectable
items weren't actually unselectable.
This broke the link inspector: if you clicked on the text
"External link", for instance (a ui.MenuSectionItemWidget), that "item"
would be selected, the link target input would be cleared, if you exited
the link inspector in any way the link would be unlinked, and any new
link inspector you opened would have a completely non-functional dropdown.
Change-Id: I7faa3d23b51b9cb93e68414584b9f433ea1f656a
Right now it's anchored to the bottom left of the category widget as a
whole, even if the text box is pushed farther to the right by existing
categories.
Change-Id: I7f2ca12b82d17c27fb3b87cb819a2a99a9fed108
Parsoid changed these types from mw:WikiLink/{Category,Language}
to mw:PageProp/{Category,Language} in I0f0a826c. We had previously
added support for them in 4d91e4ed but code overwrote the new types
with the old ones on the way out, triggering the DOM corruption warning.
Change-Id: I768ec2ffd623e5a01f18959277786697603a97f0
A very weird if statement caused pretty much all logic for displaying
the 'save' panel to be skipped if the sanity check had failed. The
result was that all buttons were displayed at the bottom of the
save dialog, even those that don't make sense in that context.
Change-Id: I628ebc05830fb25d67ff181852a1e56f0e25dee9
The code asked all media sources for a rerender and used whichever one
came in first, which meant that it might potentially render the wrong
image, or reject the promise if one source served an error response
before a good response from another source arrived.
Also reject the promise if we can't find an image source in the response.
Change-Id: I6b516ad41b8a9e2abd440625bb76f3e1abb54520
If a template was setup without a default output and returns an empty result
to the transclusion, the user could not access the template dialog because
there was nowhere to hover over to get it visible. This commit checks the
output from the template after it was rendered with the given parameters
and if it returns empty, it adds a placeholder to the output so to give
the users way to access that template's transclusion dialog and edit
or remove it.
Bug: 55810
Change-Id: Ib842b401e74d79b6382cada6bb7c6048b713977c
Replace ve.trackRegisterHandler with two methods: ve.trackSubscribe and
ve.trackSubscribeAll. The former takes an additional string argument 'topic',
which specifies a string prefix on which to match event names. The callback is
only called on matching events. The latter, ve.trackSubscribeAll, binds a
handler to all track events, regardless of topic.
This patch simplifies argument-handling by eliminating variadic ve.track calls
in favor of a single object that encodes all event data. The loose coupling of
track event emitters and subscribers makes relying on unnamed positional
argument conventions brittle; property access works better.
Change-Id: I3b58ce0f48ad3c9b56fcaa9c2226cc79bbcd4051
* Add config option to disable if required
* Centre label within resize handles
* Only show when resizing
* Sexy opacity transitions, rounded corners and multiplication
character
Bug: 54297
Change-Id: Ic49430ce3302f780ae4b05d1fa29e14db1192c84
Using the MW APIs get a resized version of the image and use
GeneratedContentNode to cache the url.
Bug: 55697
Change-Id: I418f7e1464663f447d46de7ffc29aa5f52d23b12
Resizes the $resizable element as you drag.
Can be disabled by setting the 'outline' config option.
FocusableNode
* Redraw on resize
ProtectedNode
* Destroy and prevent creation of phantoms on resize
MWInlineImageNode
* Correctly pass this.$image to ResizableNode
Bug: 54298
Change-Id: I7d6d345af8bb4712bbf154072b4704943a5a620d
* Followup 75270e24: use this.surface directly in MWMetaDialog
* Document that MWDialogTools need a SurfaceToolbar
* Namespace CE events and CSS classes with ve-ce- rather than ve-ui-
* Namespace SurfaceToolbar CSS classes correctly and put them in their
own CSS file
Change-Id: I9e70917d9c220b39e68833f67ed49fae7f7cbe6a
The default is to store the entire generated DOM node, but in
general classes can store anything that can be held by the store.
Change-Id: Ia761079fadfb5a6cfa2f00e5b5e23d6c6d3468ac
The logic requires the size of $resizable when the resizing started.
This is already stored in this.resizeInfo, but for some reason the
code recalculates every time, which is both inefficient and wrong
(but not a problem at the moment as $resizable doesn't change size
until resizeEnd).
Change-Id: I37a3c98e24b9e7d5e1970212975cef5ce9ef8a99
'resize' is actually 'resizeEnd'. Added 'resizeStart' and 'resizing'
which is triggered on mouse move.
Change-Id: I13c6e426cbcc965b3db50082c5294ca76979fe57
* For consistency with target.loading, target.saving should be either a boolean
false or a jqXHR, with the latter type indicating a pending save attempt.
* Rename 'DOM Retrieved' topic to 'performance.parsoid.domLoad' (and thus
inaugurate a convention of hierarchical, dot-separated topic names).
* Add a 'performance.parsoid.domSave', which is a near-mirror of domLoad, but
measures the time it takes to save a DOM.
* Remove three old ve.track events, because they are not used and because their
name and signature are not consistent with current usage.
- page-save-attempt
- page-save-success
- page-edit-impression
Change-Id: I54602394eee5d6d9229c01d868cb366c9f56b2c3
There was code in there once, but it's now empty. Removed it in favor
of adding explicit listeners in the handful of subclasses that
override it.
Change-Id: I160e55ad3c7d85c9f830a4bd7d42ec5dc18ad04f
* Moved isNodeFocusable to ve.ce.NodeFactory
* Added isFocusable static property to ve.ce.Node
* Set isFocusable to true on ve.ce.FocusableNode
Change-Id: I3cf666280abdfce55bf9b0710827bb25c40bfd51
This was probably correct by default on OSX but Ubuntu's
default theme uses an orange highlight, and Windows uses
dark blue.
Change-Id: I601c2d27f6d928b38799f3a6502de5be1dccc199
Was previously calling show(), which showed the context regardless
of whether one was required or not. Changed this to update().
Change-Id: I2c6c37b6b988cca60f3f3f2429476ab4b429184b
Because of the change to ButtonWidget, the button returned false after
onClick and as a result, ULS dialog didn't open.
This fix adds a fake 'href' value to the PushButtonWidget instance
in ve.ui.LanguageInputWidget so clicking the 'change language' button
continues to evoke ULS.
(Notice, this widget will soon be split into ve-MW with a smaller fallback
widget in core, but for now, this fixes the fact ULS doesn't appear when it
should)
Change-Id: I32eabdc5ee1b3681c20c756f45a3257c7a0b5681
Though the initialisation works since core has been fixed, there
are still plently of cases where we take real user input that can
genuinely be invalid.
Most notably, you couldn't make a link to [[.com]] because the
link input widget would crash on an exception from mw.Title.
Even after core was fixed (and ".com" is now valid), one still
couldn't make that link. This time because '.' is an invalid title,
and we create a Title object for that while typing ".com".
ve.ui.MWLinkTargetInputWidget#getLookupMenuItemsFromData:
* Guarded against mw.Title throwing by using newFromText
and checking it first.
ve.ui.MWLinkInspector#static.legalTitle:
* Removed in favour of checking whether newFromText returns a
truthy value.
Change-Id: I580bfccb83f86be3ad7e83d31f0834e1cde7df9c
`new mw.Title` throws on invalid input. Converting uses to
mw.Title.newFromText instead and converting try/catch to if/else.
mw.Title in general (regardless of which constructor) has been
improved in core. It will no longer crash on pages where the page
title was a false hit for invalid (e.g. we couldn't load VE on
[[.com]] because the js parser thought it was invalid).
However, though the initialisation works since core has been
fixed, there are still plently of cases where we take real user
input that can genuinely be invalid.
In cases where the code did not catch exceptions and there was
no obvious way to handle it, I left it as is (let's revisit them
in a separate commit). It would be an exception either way, and
I'd rather see "mw.Title: Parser error" than
"TypeError: null does not have method getNamespaceId".
Change-Id: I5b1b23d56d39cdb7ecb0809e3d721992e0c30f54
Fix things that 4aa86d0f8 broke:
* Update surface parameter to windowSet in all ve.ui.SurfaceDialog subclasses
* Do the same for ve.ui.SurfaceInspector subclasses
* Fix @extends documentation for SurfaceDialog
* Fix documentation for ve.ui.SurfaceInspector, copypasta from SurfaceDialog
Bonus:
* Add .getMetaList() getter to dm.Surface
Change-Id: I843e99e45e9b013cb9cb559f050384d39bbbddf2
Instead select the node and require the user to press delete
again if they really meant to delete the node.
Also test cases!
Bug: 55336
Change-Id: I66520e18740e78ce6313f9b31bb575d06b91bea8
We now initialize the surface in the dialog with a 4-element linmod
(paragraph, /paragraph, internalList, /internalList) rather than a
2-element linmod. This broke the code that disables the Insert button
in the reference dialog when the surface is empty.
Change-Id: Id733e654a628b1294e697ad4ef3f2f6fe1a9c869
Also make sure surface observers are detached so they don't try to
poll the CE when it has been destroyed. This was causing exceptions
to be thrown in test runners.
Change-Id: Ic8864a73f3ee04da6018f552b1aa68748d7ffba7
ve.EventSequencer.js:
* Initialise listener lists to []
* Call afterLoop listeners even if there are no after listeners
Change-Id: I63a0bafa74f2c3135bd3ca75adc91a57c19319ed
Major changes:
* Create a MW specific save dialog class
* Widgetize save dialog elements
* Simplification of viewPageTarget
Minor changes:
* Added getWindow method to windowSet and setTitle methods to window class
* Add transition css properties to dialog styles
Bug: 48566
Bug: 50722
Bug: 51918
Bug: 52175
Bug: 53313
Change-Id: I8c0db01fb8477a9b3d3dfe2a6073ac67869ce40e
ve.EventSequencer.js - Implement new types of event listener:
* onLoop( f ) to set a listener for the start of the event loop
* afterLoop( f ) to set a listener for the end of the event loop
* afterOne( f ) to set a one-time listener for after an event
* afterLoopOne( f ) to set a one-time listener for the end of the event loop
Change-Id: Ie388e0e9edcfccaa20e04c649a8b85d028ddde9c
What I learned today:
* Window doesn't have a scrollTop property, body does (that's why animate
doesn't work on window)
* jQuery.scrollTop() doesn't work on body (in firefox) but works on
window everywhere
* jQuery.scrollTop() uses scroll offset, not the scrollTop property
* Body doesn't have an onscroll event, window does
What I really learned today:
* Browsers are very poorly designed
Objective:
* Make clippable elements properly resize in Firefox when scrolled
Diagnosis:
* Scroll events were not being emitted from the scrollable container
after the merge of Ifec0dae598f7fd99270588bd8ca77777a07e9669 because
such events are not emitted from body tags, only scrollable divs and
windows
* jQuery.scrollTop was giving incorrect values when called on the body
instead of the window, so also due to the aforementioned change, the
clipping was being calculated incorrectly
Treatment:
* Add $clippableScroller property, which is either a scrollable div or
the window (could this have side-effects if someone did something
ridiculous like made the body absolutely positioned and overflow:auto?
Yes, but I have no other option and that's a strange edge case don't
you think?)
* Use $clippableScroller for listening to scroll events and getting the
scrollTop value from jQuery
Bug: 55343
Change-Id: I819aba60b200059886b347115fda437b3dc9cb7a
Objective:
* Remove surface dependencies in dialogs, inspectors, windows and window sets
* Introduce surface-specific versions of dialogs, inspectors and window sets
Change-Id: I2db59127d2085b02e173a3605e174317e419e213
After 6ec34a3de the edit notice button was no longer hidden by
default if there were no notices. The alert icon was always
visible (when clicked it would show "0 notices").
In addition, on any page (except pages with edit notices) it
would throw a fatal exception at load time because method .hide()
doesn't exist.
As a result, current master shows an incomplete toolbar (e.g. not even
a Save button!)
Change-Id: Ib6e91c4756664c25fbb7403ef54b4fffcc0f9938
Class ve-init-mw-viewPageTarget-pageTitle added various
transition settings that were never used. Meanwhile, we're doing
fadeTo which sets inline opacity css every X ms until the
animation is finished.
* Changed the inline jQuery animation to use css transitions
instead.
* Removed the inexistent and obsolete ms-transition declaration.
* Removed ":visible" from selector query. This makes the selector
more performant (since :visible is a proprietary Sizzle keyword)
and it was obsolete anyway. The classes don't affect display none/hide,
this is handled naturally by the browser now.
Change-Id: Ibdfb442ff6c743ef16b514a7696796ee27821887
When deactivating before the surface became active (e.g.
this.active is still false, as case is the case when Parsoid
isn't running), the teardown sequence was incomplete.
Most notable, the page title (h1.firstHeading) was still dimmed
after cancelling the alert for Parsoid error, eventhough
everything else was shown and restored.
* Moved call to #showTableOfContents in #deactivate up for
consistency with #activate.
* Added call to #restorePageTitle in #deactivate so that the
title is restored even if the surface didn't activate yet.
* Removed calls to various methods in #tearDownSurface that
were already called by #deactivate.
Now activate/deactivate and setUpSurface/tearDownSurface are
in balance.
Change-Id: Ibb2fbf0e5ab9b6a028d4e139c13aa7ff8c82be82
Previously we returned ElementLinearData from the converter, then
stripped out the MetaLinearData. This meant that before processing
the ElementLinearData from the converter actually contained metadata
which is confusing.
The new document constructor stores the converter results in a
FlatLinearData object and simultaneously populates element and meta
data stores.
Also in this commit I have moved various methods from ElementLinearData
to FlatLinearData, from which ElementLinearData inherits.
Change-Id: I64561bde2c31d8f703c13ac7b0a0c5f7ade9f3d4
When the editor finishes retrieving the target DOM, fire a 'DOM retrieved'
analytic event with the following properties:
* Response time in millisecond.
* Response size in bytes.
* Whether request was a cache hit.
* Value of X-Parsoid-Performance header (or null if unset).
jQuery.byteLength is now a dependency for ext.visualEditor.mediawiki.
Change-Id: I74d3964238927645e847b6e215991bd6b1ebad59
Objectives:
* Use widgets to render toolbar actions
* Remove labels next to help notices and edit notices buttons
* Add a close button to the help notices and edit notices
Overview:
* ve.ui.ButtonWidget is now abstract, use ve.ui.PushButtonWidget instead
* ve.ui.IconButtonWidget now inherits from ve.ui.ButtonWidget
* ve.ui.PopupWidget's display method no longer takes x and y arguments
* Fixup naming issues in MWCategoryPopupWidget
* Fixup naming issues with some ve-init-mw CSS classes
* Rename ve-mw/ui/styles/ve.ui.Widget.css to ve.ui.MWWidget.css
* Change uses of "callout" to "tail"
* Add hyperlink functionality to buttons
* Make buttons accessible through focusing, but make unfocusable by
clicking
* Add head option to popup for rendering a title and close button
Bug: 52386
Change-Id: Iea2c8df1be64d40f9c039873d89ee540cc56e687
Objective:
* Use <body> instead of the closest surface overlay as the default
overlay (wasn't actually being used anyway)
* Use this.$.offsetParent instead of closest surface when measuring
parent frame offset to position text input menu
Change-Id: I04fc5ff1da4bafd342093922a5bd3b3a784b327c
This commit extracts the page and outline handling logic from
ve.ui.PagedDialog (RIP) and moves it into two layouts: ve.ui.PagedLayout
and ve.ui.PagedOutlineLayout, respectively. These layouts are now implemented
inside the dialogs that used to mixin the ve.ui.PagedDialog class. This
brings a much cleaner separation of concerns between Dialogs and Layouts
and allows the use of page handling logic without the accompanying
outline logic.
Change-Id: I5efa2f893f4b7e962438b3aff34b737573bbd5ca
Ignoring all bounced change events led to the logic for unhighlighting
the previously selected FocusableNode being skipped. This caused a bug
where if you clicked a FocusableNode, it would stay highlighted even
if you then selected some text, until you highlighted another node
(which would then be highlighted forever, etc.)
Change-Id: Ia8d74ef85eaa47326d49ef6c0f395b44b90da4dc
Objective:
* Make ve.Factory behave like ve.NamedClassFactory
* Remove the only remaining use of ve.Factory (actions)
* Remove ve.NamedClassFactory
Change-Id: Ie302ef5ea31081de7ab0db6091058a59946aef4c
Objectives:
* Pass a specific tool factory into a toolbar, allowing it to be used
with different collections of tools and not depend on the
ve.ui.toolFactory global
* Move syntax highlight editor tools to their own factory
Change-Id: I307bf180bd6817bc044bc474a77861e13f431ddb
InternalList.clone() assumed that all properties are automatically rebuilt
when a new document is built, but that's not true for .nextUniqueNumber
(or for .itemHtmlQueue for that matter). This meant that, in practice,
.nextUniqueNumber was being reset to 0 after auto/N numbers for existing
references had been assigned, but before assigning numbers to newly
created references. This caused all sorts of naming collision fun.
Bug: 54712
Change-Id: I1d087a5f3c23979d7d488e3ab32eb064ebc23e94
Document slice only ever contained linear data, with extra functionality
to preserve the range. It pre-dated LinearData, but now we should
refactor it to reflect its purpose.
Change-Id: Ifc908f7526c83a43a51372c8d2494d7260e7facd
We already getSlice which returns a ve.dm.DocumentSlice, so using
the word slice in this method is very confusing. What we are actually
doing is creating a ve.dm.Document from a range. Also remove argument
overloading as it's not particularly helpful and would make the new
name a lie.
Change-Id: I93da3419510410b170396e6765fbe2a87f9795be
The way we implemented undoing transactions was horrible. We'd process
the original transaction, but with a reversed=true flag. That meant we
had to keep track of the 'reversed' flag everywhere, and use ternaries
like insert = reversed ? op.remove : op.insert; all over the place to
access transaction operations. Redo then worked by reapplying the
transaction. We would verify that this was OK by tracking whether the
transaction was in an applied state or an undone state.
This commit makes it so every transaction can only be applied once. To
undo, you obtain a mirror image of the transaction with tx.reverse(),
then apply that. To redo, you clone the original transaction with
tx.clone() and apply that. All the code that had to use ternaries to
check whether the transaction was being applied in reverse or not is
gone now, because you can only apply a given transaction forwards,
never in reverse.
Bonus:
* Make ve.dm.Document's .completeHistory a simple array of
transactions, rather than transaction/boolean pairs
* In the protection of double application test, clone the example
document properly; it modified ve.dm.example.data, which was "fine"
because it ran .commit() and .rollback() the same number of times
Change-Id: I3050c5430be4a12510f22e20853560b92acebb67
In jQuery 1.8, if you focus something using jQuery, the jQuery focus
event fires before the jQuery blur event, which is wrong. If you focus
something natively, the events do fire in the correct order.
See http://jsfiddle.net/WGy9h/4/ .
Fortunately, the native events always fire in the correct order, so
listen to those instead. Normally, we're not concerned with the order,
but in ce.Surface we bind the same focus/blur handlers to a pair of two
nodes, and then if the focus moves from one to the other, we'll get
confused by the events being emitted in the wrong order.
Change-Id: Ia585b42b6deb74ba55a2d55ce1922b1e04d85e81
Currently we just say 'group ""' which is a bit weird, so
instead have a specific message which talks about the
'default group'.
Bug: 51873
Change-Id: I4a17f15ee18175fac11b36b102a06cc9714426ee
Update: Switched to generic ve.ui.Toolbar and ve.ui.Tool for consistency
with VE in general. Changed searchbox to floating and hidden by default.
Call for search using shortcut key. Overriden ESC key.
Node handler for <syntaxhighlight>'s Rdfa type.
Embedded in VisualEditor.php with its own ResourceLoader module.
Use $wgVisualEditorEnableExperimentalCode in LocalSettings.php
to load the module.
Supported languages (for testing): text, javascript
Features:
(1) Internal mechanisms:
(1.1) Tokenizer. Tokenize input code string.
(1.2) Highlighter. Highlight based on predefined rules.
(1.3) Syntax checker. Validate based on predefined rules.
(2) SimpleSurface:
(2.1) Auto indenter. Works with (){}[] blocks.
(2.2) Reformatter. Reformats spaces and remove trailing
whitespaces.
(2.3) Language selection dropdown.
(2.4) Basic editing. Insert, deletion, selection.
(2.5) Clipboard & edit history support.
(2.5.1) Undo (Ctrl + Z), redo (Ctrl + Y)
(2.5.2) Copy (Ctrl + C), cut (Ctrl + X), paste (Ctrl + V)
(2.6) Search & replace. Ctrl + F to quickly move focus to search
box.
Bug 47742
Change-Id: I4adede9e05fd2236cee50ce03f597e8ff6b1914d
This change allows for the Username to be sent in MWBetaWelcomeDialog
title so the i18n message can support {{GENDER:}} parameters.
This change arose from the need to provide GENDER support when translating
the welcome message from Change-Id: I6a3da40b286bb1abd2aff360dab3b386deb13420
Change-Id: Iae70fbaa5be822d571a0d75704cfeca4eabd2fe8
.text() returns empty for comment nodes, where textContent returns
the contents of the comment node.
Change-Id: I5e2798a6dba9d0f8fc13d5c0f78fe1fd255f1ebe
When you cursor onto a FocusableNode, it's selected, and we focus the
paste target as part of our hack to make copying FocusableNodes work
in Firefox. But then when you press the arrow key again, that event
isn't picked up by anything, and you can't move the cursor off the
FocusableNode using the keyboard.
Fixed by attaching the EventSequencer to this.$ (which is the parent
of $documentNode and $pasteTarget) and listening for focus/blur on
both $documentNode and $pasteTarget.
Bug: 54443
Change-Id: I7bddcfa9fa6f38908e315c97623bd27133daa98d
ve.ce.Surface.js
* changeModelSelection: store selection temporarily for bounce detection
* onChange: do nothing if bounce is detected
Change-Id: I758e7a72a5690463f12f456419c6e471dd29a9db
Due to Firefox' Ctrl-A creating an outer selection (0,len) as
opposed to inner select like in Chrome (1,len-1), deleting leaves
the document completely empty (with no cursor anywhere in the
document).
However, setupSlugs() wasn't inserting a slug because the internal
list still existed (so this.model.length !== 0).
Using this.$.children().length instead.
Bug: 50947
Change-Id: I1517ebcc5b31e2544559b851174482b0c872b24b
Logic was failing because we were passing the index of the annotation
within the AnnotationSet, instead of the index within the Store, to
containsIndex().
Bug: 54332
Change-Id: Ibfd9abe6e4b44d9db744e0c5019418eee12f84a4
Sometimes, .clip() would be called when clipping had already been
disabled again, and accessing this.$clippableContainer would cause
an error. This happened to me when typing quickly in MWLinkInspector.
This probably happens when enabling and disabling clipping right after
each other in response to the same event, such that the setTimeout()
for the initial clip is run after clipping has already been disabled.
Change-Id: I0f85ea5f10955188bae51160e1c88eca858ea1bf
250ms after the user stops typing, we rerender the node with what they've
typed so far.
Bonus:
* When using MathJax, tell it which node to rerender
* Avoid crash when trying to unwrap wrapper paragraph
Change-Id: I623eef48e40d480cc98766cf7daf75dacd0bde19
Pass an extra parameter to show() to let it know when the menu is
just being moved, and therefore doesn't need to perform the fade-in
transition.
Change-Id: I2cf2ff07db6cc7d226f3d626755792a06dfcbe54
Move the triggering of the rerender event into an overridable method
'afterRender'. Some nodes don't have the correct dimensions
immediately after rendering their DOM elements as they may need
to wait for images to load, or for a script to run (e.g. MathJax)
Change-Id: If204f665dcb2fd69d00a183279056d11188ddd74
Replaces newFromNodeReplacement(). newFromNodeReplacement was very
simplistic and didn't support metadata or internal list items, so
if you had comments or references inside of the data you were editing
(reference contents or an image caption), they'd get mangled.
With this, you can do:
newDoc = doc.getDocumentSlice( node );
// Edit newDoc
tx = ve.dm.Transaction.newFromDocumentReplace( doc, node, newDoc );
surface.change( newDoc );
and that takes care of metadata, internal list items, and things like
references that reference internal list items.
ve.dm.Document.js:
* In getDocumentSlice(), store a reference to the original document
and the number of items in its InternalList at the time of slicing
in the created slice. This is used for reconciliation when the
modified slice is injected back into the parent document with
newFromDocumentReplace().
ve.dm.InternalList.js:
* Add a method for merging in another InternalList. This provides a
mapping from old to new InternalList indexes so the linear model data
being injected by newFromDocumentReplace() can have its InternalList
indexes remapped.
ve.dm.Transaction.js:
* Replace newFromNodeReplacement() with newFromDocumentReplace()
ve.ui.MWMediaEditDialog.js, ve.ui.MWReferenceDialog.js:
* Use getDocumentSlice/newFromDocumentReplace for editing captions/refs
* Change insertion code path to insert an empty internalItem/caption, then
newFromDocumentReplace into that
* Add empty internalList to new mini-documents
ve/test/dm/ve.dm.Transaction.test.js:
* Replace newFromNodeReplacement tests with newFromDocumentReplace tests
ve-mw/test/dm/ve.dm.Transaction.test.js (new):
* Add tests for newFromDocumentReplace with mwReference nodes
ve.dm.mwExample.js:
* Add data for newFromDocumentReplace with mwReference tests
VisualEditor.hooks.php:
* Add new test file
Bug: 52102
Change-Id: I4aa980780114b391924f04df588e81c990c32983
* Check the popup fits within the node horizontally as well
as vertically before embedding.
* Calculate the position of the node relative to the document.
Previously we assumed the parent was the document and so used
jQuery#position but this is not the case if a custom $focusable
is passed to FocusableNode.
* Forcefully re-show the context menu on resizable node mouse up.
This is apparently done automatically by a redraw event, but if
the user just clicked on a resize node without dragging the context
menu would be lost.
Change-Id: Id477a30827c9393a446e9c44466c83dabc7e0ab4
Documentation says third argument is 'data' when in fact it is
'insertion' which is then re-used as the result of fixupInsertion :/
Change-Id: I17c959f858eddddc90a6fa839da0d32da69a784f
Function was removed in eb64743436 but one caller was still left,
which caused VE to throw a JS error when opening the reference dialog
to insert a new reference.
Change-Id: I827381bfe3bdeecdbaa1fba55a09b3e8e03575a6
This is obviously necessary, but wasn't done, so calling update()
with a config object was broken.
Change-Id: I30d67bcb117885c792c0f08ea55d60cb294de18b
If you changed the contents of an alien tag extension, then tried to
use undo, the change wouldn't be undone, but the undo state would
toggle.
This was because we only kept one copy of the data-mw object for these
nodes and modified that one copy. Instead, create a new copy every time
we modify it, so we can actually go back to previous states.
Change-Id: Ib4d5d460a6fdda9c3b0968f269585d620b47fdd8
When you press delete inside an empty node (e.g. Heading) that
node should be removed, instead of the paragraph beneath it being
merged into and effectively converted. If the heading is non-empty
then merging is still the correct behaviour.
Also add in test case.
Bug: 50254
Change-Id: If9cee79feb4b4ee9d7c367e392b00fee5e8c0669
When the document starts with a focusable node, and we try to initialise
the selection to [1,1], the current logic does not detect that as being
on the focusable node and tries to do a native selection.
Bug: 54446
Change-Id: Ib515c435314c35c4e9b3802da117b963b3ef4169
this.$ on a GC node is just a wrapper, so shouldn't take the
HTML attributes from the model, otherwise you may end up with
double borders and padding.
Change-Id: I5641df341c9b118461e7e8fb89266dd300e09755
In various places in the UI code, certain properties of config objects
were overridden and in some cases the configurations were documented as
private as a strange hack to prevent them from being advertised in the
docs.
I, Trevor, have been convinced of the error of my ways, and gladly
reverse this situation, allowing all configurations to always be
overridden when desired, while still allowing default values.
Change-Id: I242e3b1902dec8e09eeea38fa64381e69ee04215
In this instance, MW(Extension|Reference|Transclusion)Nodes.
In general anything that is focusable should probably be relocatable
by default. We should considered this when we sorting out the
focusable/protected/relocatable mess in the near future.
Change-Id: Ifc55e251cba3e875798d5103540d02ad651399ad
Fixing a couple of mishaps in the language annotation, including adding a
getComparableObject in the ve.dm.LanguageAnnotation class.
Change-Id: Ia28900df55969f60576cfd716c70ffc1ba5f4c27
Some browsers normalise attributes (e.g. Firefox makes
URLs absolute) so we have to remove them from the clipboard
hash to make the comparable.
Bug: 54377
Change-Id: Iadc4d886a5345b28370cbfa31eb665661e577eeb
Conversions usually end in a close tag so this hasn't been a problem
before, but the mini-conversion we do in onCopy may not be balanced.
Change-Id: Ia2db29f116ca84ee886b4c5cafd4ac45cd926b79
Simply generating ':3' as the "unique" name for the 4th reference
doesn't work. Even if getUniqueListKey() had been used, that only
checks for conflicts with names that have already been encountered
(i.e. occur in <ref> tags that precede the current one), not for
conflicts with names that first occur further down in the document.
The solution is to generate names at serialization time, when we
have full knowledge of which names are in use. Internally, we use
'literal/<name>' for names that literally appeared in the source,
and 'auto/<number>' for unnamed references. Then at serialization
time, we translate 'auto/<number>' to 'literal/:<number>' if needed
(i.e. if the reference was reused).
ve.dm.MWReferenceNode.js:
* toDataElement()
** Prefix listKey with literal/ or auto/ as appropriate
* toDomElements()
** Map auto/ listKeys to unique names
** Don't try to unset the name if not present (was unsetting a property
that didn't exist anyway)
ve.dm.InternalList.js:
* Remove now-unused isUniqueListKey()
* Rewrite getUniqueListKey()
** Make prefix configurable
** Take previously generated unique keys into account
** Map the same old key (auto/N) to the same generated key (literal/:M)
* Add getNextUniqueNumber() as a source for auto/N numbers: previously
used the length of the itemHtmlQueue, but that only works during
conversion, not from the UI dialog
ve.ui.MWReferenceDialog.js:
* For new references or conflicting names, generate an auto/N key and
let toDomElements() deal with actually mapping that to name
ve.dm.InternalList.test.js:
* Rename listKeys to new style
* Split the test case into two groups so we can test multi-group cases
* Add tests for getUniqueListKey()
ve.dm.mwExample.js:
* Rename things to new style
* Modify the test case so it attempts to trigger bug 54341
Bug: 54341
Change-Id: I726fb83e6fb66ffec643d996768a854ec9474b3d
Because there's no sane wikitext to handle that case, and Parsoid
will just output garbage.
Bug: 53151
Change-Id: I9e065aa46d88f6bed9c47127b3e002ec2e1fec5a
When we switched all base 64 encoded blank GIFs to the "stable" version,
we created a regression that prevented proper styling of the drag marker.
This restores the correct drag-drop experience.
Change-Id: I9c2a195fd866a5919245667a436106772debcffd
Correct the return value descriptions for the `newFromMetadataInsertion` and
`newFromMetadataRemoval` methods (which appear to have been cut-and-pasted
from another method).
Change-Id: I019b0ef9c75ff47fc0f2df8c95da9d090710a5a8
Code with a similar purpose was added in 568e0e5701 but got lost
when some things were moved from ve.Surface to ve.ce.Surface in
5012ed10.
Initializing the selection at (0,0) was known to cause problems before,
and since 789d0caf09 breaks editing of empty documents: typing in an
empty document begins in an inline slug, but SurfaceObserver doesn't
notice typing in an inline slug unless the ce.Surface pawns it, which
is OK because insertions in slugs are always pawned, but the pawning
logic believes the cursor to be at offset 0 where there is no slug
(it's at offset 1) and so it doesn't pawn.
Bonus: update tests and add descriptions for dm.Surface.change tests
Change-Id: Id72314d0fe650dacc7cdb842f5cea2f3bfba5145
The Parsoid team has changed their spec to always use multi-part
format even for one-part transclusions. This commit changes VE's
output format to always be multi-part, but still accepts single-part
format on the way in.
Change-Id: I6b3156b0b599ad042bb52d7f53dcdeb1c4a0954a
Cucumber 1.3.6 seems to be problematic:
gems/cucumber-1.3.6/lib/cucumber/rb_support/rb_language.rb:122: warning: redundant nested repeat operator: /^** This is a new line/
Updating the rest of the gems too.
Change-Id: Ia173312baa178a45d648fc537c8abf914144bbd5
* Convert some spaces to tabs
* Move private function to top and document
* Give constructor a global name
Change-Id: I7ec144303d32b1bb454b4164222601c263fb75bf
Toolbars may want to control the target as well as the surface (spoiler alert!).
The new TargetToolbar has a pointer to its target as well as its surface.
Change-Id: I928316d9e23ac3f3de3e76c34ef0ac3d27855ab3
Objectives:
* Scroll when needed to show highlighted (with keyboard) or selected (by
any means) options in select widgets
* Allow clipping and automatic scrolling for certain elements when they
are otherwise going to be rendered partially out of view
Changes:
*.php
* Add links to new file
ve.ui.Widget.css, ve.ui.Dialog.css
* Removed unneeded x-axis overflow rules
ve.ui.ClippableElement.js, ve.ui.Element.css
* New mixin, adds visible area clipping support to an element
ve.ui.PopupToolGroup.js, ve.ui.MenuWidget.js
* Mixin clippable element
ve.ui.OptionWidget.js, ve.ui.OutlineItemWidget.js
* Add scroll-into-view configuration for option widgets
ve.ui.SearchWidget.js
* Scroll items into view when highlighting with keyboard
ve.Element.js
* Add getBorders, getDimensions, getClosestScrollableContainer and
scrollIntoView static methods
* Add getClosestScrollableElementContainer and scrollElementIntoView
methods
Bug: 53610
Change-Id: Ie21faa973a68f517c7cfce8bd879b5317f536365
Sometimes GitInfo returns a version ID of false if it can't
find the right files. In this case we should hide the whole
message as it is meaningless.
Bug: 53050
Change-Id: I71161df7588aa9311bc1fdf6b064cc6d8c155f61
Previous was checking by string match to 'preformatted' which didn't
match 'mwPreformatted'. Now using node factory to see if
hasSignificantWhitespace is set.
Bug: 54083
Change-Id: I1be2d4568df7848e08074d200fb374acd508f6fa
These were meant to have been de-experimental-ised with the toolbar
commit; oh well. This moves the following text styles from being in
"experimental" mode to being regular annotations:
* Code
* Strikethrough
* Subscript
* Superscript
* Underline
Change-Id: I21be2dc844b47b825d7a1e48a592067166ecd122
The previous implementation couldn't deal with transactions that
replaced both data and metadata at the same time (rather than replacing
data while moving metadata around), and extending its approach to
deal with that case would have made it much more complex.
So I rewrote the algorithm from scratch. The previous implementation
scheduled deferred moves for existing items, but immediately processed
insertions and removals. This is problematic for replacements and
maintaining the order in the binary search list. So instead, this new
implementation builds an array representing what the new item list
should be, then processes insertions, removals and moves in the correct
order to achieve that state.
It looks like the previous implementation didn't always work correctly,
which was masked because the test suite passed full=false to
assertItemsMatchMetadata(). This rewrite fixes this.
Also remove setMove/applyMove from MetaItem, because we don't need them
anymore and they're evil anyway; and add isAttached(), because the new
algorithm needs it.
Change-Id: I899d2b3c94c2cfa55823879bca95456750f64382
This was already possible in the operation structure by using
removeMetadata and insertMetadata, but no transaction builders
generated transactions like that.
With this change, pushReplace() can be instructed to overwrite the
metadata with arbitrary data rather than collapsing it by passing the
optional insertMeta parameter.
Change-Id: I0272fe38e053161c738591cf0a7b447a0827d4dc
Transactions that replaced metadata twice at the same offset
(with retainMeta-replaceMeta-retainMeta-replaceMeta) were broken
because the processor for replaceMetadata didn't advance the
metadata cursor.
Change-Id: I7ad24e7ffb4c39b40ec9c347db301f8e28f3692d
Changes:
* Remove reference to inspector close method, which didn't actually exist
* Use more spacy array syntax for all action methods
Change-Id: I08ee2d262acc7b39456766fb4a0b490da88ad041
Add some test cases for documents with trailing metadata, and fix an
off-by-one error in the metadata-mutating transactions (since the
document metadata array is one larger than the document data array).
Change-Id: I8f049466e03ed55010dfcf0a35702536edfa7b0a
Currently, WindowSet open method uses the Window factory to call up
the instantiation of a new dialog or inspector class. This commit will
also allow sending further config options to these classes if needed.
Specifically, this will also allow the use of ve.ui.Context.js for
block inspectors that are not dependent on current selection or current
location of the cursor.
It will also let us generalize the dialog/inspector window instantiations
by adding in any needed config settings on call.
Change-Id: If14384d74ab91ef01b1c7641ff84f327f2a12112
Restructure SurfaceObserver methods so that the method calls are more precise.
modules/ve/ce/ve.ce.SurfaceObserver.js
* Move timing code into startTimerLoop / stopTimerLoop / timerLoop
* Move poll logic into pollOnce
modules/ve/ce/ve.ce.Surface.js
modules/ve/ui/ve.ui.Surface.js
* Change all surfaceObserver calls to use new API
Change-Id: I0085e4a53c5a776733dce6944b867b8d2228ba4b
Firefox:
* Doesn't fire events without a selection, so when all we have is a
focusable node, create a dummy selection in the paste target so the
browser triggers an event on command+C.
Clipboard keys:
* Instead of just creating a text hash which may or may not match up
with the plain text in the clipboard data, just convert the clipboard
store into an array and use the index as the key. Also prepend a
random number (clipboardId) so on paste we can verify the copy came
from the same CE document.
The text hash is now used for validation if only HTML is written
to the clipboard.
HTML:
* Instead letting the browser grab CE HTML, always get DM HTML from
the converter as it is cleaner (no phantoms, linefeed markers, extra
class names etc.), and will make cross-ve-instance pasting easier
in the future.
Clipboard overriding:
* Always override the clipboard with the above HTML, either using
clipboardData.setData if it is available (webkit) or by throwing
the HTML into the pasteTarget and selecting it during pre-copy.
Bug: 53375
Bug: 49396
Bug: 52096
Change-Id: Id0f39c10818047bb4b8922e97cead153a770757f
These are not considered errors in jsduck 4.x but are in 5.x.
Though we don't specifically want to support 5.x yet, these are
actually genuine errors that were already causing incorrect
documentation to be generated, even under 4.x (it just doesn't
warn for these under 4.x).
Not from 5.x warnings, but fixed while at it:
* Removed more redundant @method
* Added a missing @returns for ve.Range#flip
* Added newline at EOF
Change-Id: Idc22b46b082a813e8e1761403e1ebf908bf690c4
This version pushes a `replaceMetadata` operation after a `replace` to
fixup trailing metadata if there is no inserted region and the removed
region includes metadata. This avoids a corner case where the
size of the metadata arrays inserted/removed in `Transaction.pushReplace()`
do not match the size of the data arrays inserted/removed.
We remove the now-unused `Document.getMetadataReplace()` method.
We also adjust `MetaList.onTransact()` so that it continues to work
properly when the number of metadata entries in `replace.insert` is
not the same as the number of metadata entries in `replace.remove`.
Change-Id: I1d600405b855ca1cb569853bb885b0752df47173
The `Transaction.pushReplace` method has a corner case if the removed
region has metadata and the inserted region is empty. This works fine
unless there are two adjacent `pushReplace` operations, which can occur
in `Transaction.newFromUnwrap`. Fix this by having `pushReplace` look
at a preceding replace and correctly merge the two operations if
possible (in particular in the tricky case where the previous case has
a zero-length insertion). Pleasantly, this can be done without a lot of
special-casing code in `pushReplace` or `newFromUnwrap`.
Add test cases verifying the `newFromUnwrap` works correctly (both
in commit and in rollback) when there is metadata present.
Change-Id: I6cfec0d2b1823dad724422f018a3c73dc0c7f186
CODING.md
* Document the procedure for adding a new javascript class
ve.dm.MWExternalLinkAnnotation.js
ve.dm.MWInternalLinkAnnotation.js
ve.dm.ElementLinearData.js
ve.dm.LinearData.js
* Add whitespace line before preformatted code to fix a
rendering bug
Change-Id: I54443ea3d4799328655d279f379d4ddc176c50a0
It's important in case of replacing root element ($) of a node, so new element
does have CSS class and contenteditable property set.
Change-Id: Icf14e2164e89114e6b7c10672b782d02f4c5daac
Doing retainMetadata followed by a replace (not replaceMetadata)
doesn't make any sense and its behavior is undefined, so don't do that
in the test suite.
Change-Id: Ica032b0a5122d24e40e43e3eb43fea940270aece
* Replace addOuterLength with a recursionDirection as we only
want to add length when the first recursion was to the left,
and add nothing if we recursed to the right.
* Use isContentEditable which is the proper calculated boolean.
contentEditable is often just (string)'inherit' :/
Mercifully this works in in IE.
* Only check for the IE ce bug if we aren't recursing at all.
Bug: 53766
Change-Id: I247d1b68484cb510335b5f6789269ec254376cfe
Previously they were rendering hidden spans.
Remove hiding from internal items as they have no rendered parent.
Change-Id: Iacc12715900123cd5ab0ddefa713e57e9bea0d1b
Otherwise, changes to deeply nested structures like template blobs or
references will leak from the data model into the clipboard data.
Change-Id: I85d8d311f676d45856f30b3747e7383c70c95460
Objective:
* Make the welcome dialog work with smaller fonts by increasing its
size a bit, and also making its contents scroll vertically if needed
Changes:
ve.ui.MWBetaWelcomeDialog.js
* Move content into a scrollable and padded panel layout element
ve.ui.MWDialog.css
* Remove padding, now provided by panel layout
ve.ui.Dialog.css
* Remove min-height override, inherited value is fine
* Use max width and height instead of setting them directly
Bug: 52667
Change-Id: Ie35b041e13ef18ffcacef6d9e70439e4e1351e0a
Correcting the language span tool so the ve.ui.LanguageInspector has
static name changed from 'language' to 'meta/language'
Change-Id: I66fd3d2558663c9f1304365a11fd1276e204a7e7
The context menu was being positioned incorrectly for small inline
nodes, such as references or small templates. This fix moves the context
to the bottom, as well as placing it on the right or left in LTR and RTL
directions respectively.
Change-Id: I55de2a6464d0544e32118bf95dbb85c33354f025
ve.dm.MetaLinearData.static.merge( [ undefined, undefined, ... ] )
returned [ [] ], make it return [ undefined ] instead. This allows
us to lazily use the merge function to create metadata without having
to worry about denormalizing undefined to [] all over the place.
Change-Id: I41fe6472c2185a6315119a546a73765966d013d3
modules/ve/ve.EventSequencer.js
* Class to sequence pre-event and post-event listening correctly
demos/ve/eventSequencer.html
* Plain HTML example page for testing EventSequencer and event sequences
Change-Id: I4ddb10a30c2f44015136a7978a185d0b13f0690b
In commit e1f8ee7 the return statement was moved into the
userPrefEnabled check, however addClass( 've-available' ) was
still unconditional. This has now been restored.
Change-Id: Ia59bfed93a8849a529cc3b9d1d2e0619d65240d4
Avoid making a copy of the entire data array by using `doc.data` and
`doc.data.getLength()` instead of `doc.getData()` and
`doc.getData().length`.
Get rid of some unnecessary conditionals in `Transaction.newFromWrap`: the
`tx.pushReplace()` and `tx.pushRetain()` methods will already gracefully
no-op if the replaced/retained region is empty; we don't need to add
extra control flow to handle that case.
Clarify offset math in `Transaction.newFromWrap`.
Fix a minor bug in `Transaction.newFromInsertion`: the final retain didn't
account for the length of the removed region, if `doc.fixupInsertion`
creates one. (This usually doesn't happen.)
Remove an inaccurate TODO in `Transaction.pushReplaceMetadata()` -- it is
no longer a straight copy/paste of `Transaction.pushReplace`, so a refactor
isn't really called for.
Change-Id: I7d86a2449978365d69d4a5ed43116c2e9945475d
Objective:
* Add keyboard shortcuts for paragraph, heading 1-6 and pre-formatted
Testing:
* Using [control+num] triggers appears to work well on Chrome, Safari, Firefox and Opera on Mac
Changes:
ve.init.Target.js, ve.init.mw.ViewPageTarget.js
* Add formatting commands to targets
ve.ui.MWFormatTool.js
* Add mediawiki specific format tools and commands
ve.ui.CommandRegistry.js
* Add commands for all formatting tools
ve.ui.TriggerRegistry.js
* Add triggers for formatting tools
Bug: 33512
Change-Id: I5d6176eff50aa3cea72aed226ca06512629412d4
Objectives:
* Got rid of mw prefixing in tools, inspectors and dialogs
* Simplify tool classes so they can be generically used as items in bars, lists and menus
* Add support for a catch-all toolbar group
* Simplify tool registration, leaning on tool classes' static name property
* Move default commands to command registry
* Move default triggers to trigger registry
* Get language tool working in standalone
Change-Id: Ic97a636f9a193374728629931b6702bee1b3416a
In ve.dm.Document.getMetadataReplace(), we used to only merge metadata
if the amount removed is larger than the amount inserted. But this
could end up putting metadata in odd positions, for example if you
have Foo[[Category:Bar]]Baz and you delete 'ooBa' and replace it with
{image}xxx{/image}, then the category ends up inside the image.
We should always merge metadata when a segment is deleted, so that it
appears outside any new structure added.
There's a weird corner case here when a segment is removed but no
insertion is made: the removed metadata then needs to get glommed onto
the next element. We extend the insert/replace metadata array
when this happens.
Bug: 53444
Bug: 53445
Change-Id: I51d55fb370b473273f9cf152fdd0f356377d4109
See also http://stackoverflow.com/a/13139830/319266:
> Some are unstable and cause CSS glitches. [If] you have an
> <img> and you use the tiniest transparent GIF possible, it
> works fine[. if] you then want your transparent GIF to have a
> background-image, then this is impossible. For some reason,
> some GIFs such as the following prevent CSS backgrounds (in
> some browsers).
>
> == Shortest (but unstable) ==
> data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
>
> == Stable (but slightly longer) *use this one* ==
>
> data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7
>
> Also: don't ommit image/gif. This will break in several browsers.
For the record, this is not limited to rare browsers.
It also affects latest Chrome in some cases as confirmed by
Christian (it'd be white instead of transparent in some cases
when uses as a css background-image without border).
Change-Id: If9ff8a0820c217b6c23e3335944907939a37bef7
ce.MWExtensionNode
* Build up the wikitext for round-tripping using jQuery, and pass
through the attributes from data-mw
dm.MWExtensionNode
* Use a static getExtensionName to correctly get the extension
name from the dataElement (as the getMatchRdfaTypes hack won't
work for MWAlienExtensionNode's)
dm.MWAlienExtensionNode
* Implement new static getExtensionName function
Bug: 53543
Change-Id: Id4e83c14ec68c3b3970d05317477f19aaf31abe4
Currently we only offer the normalised page title from the server
so 'iPhone' only suggests 'IPhone'. With this fix we offer the typed
text as the first suggestion if it matches via mw.Title, so 'iPhone'
suggests ['iPhone', 'IPhone', ...]
Bug: 50452
Change-Id: I05cc0cd19537cbfa682d7aac0f9640decea282b5
And actually use this functionality on MWBlockImage to
highlight centred images correctly.
FocusableNode
* Actually use $focusable to render the highlight correctly
ProtectedNode
* Allow a $phantomable element to define which element to
highlight on mouseenter
* As phatoms are built off shields, make sure a shield is
given to $phantomable
RelocatableNode
* Allow a $relocatable element to define which element the
relocatable marker is measured against
ui.Context
* Use $focusable (when available) for positioning the popup
Plus some documentation fixes
Change-Id: I370337239af4fc935cd86757b3ce03011bae5ba8
The search index was only being built on initialization, rather than at
the time the list was being shown. By moving it to be built on open
the list will always be fresh. Also, just after building the index, we can
enable/disable the select existing button based on the number of
results.
Bug: 51689
Bug: 51848
Bug: 52000
Change-Id: Ib38b1b227edc3d61dc49fa58999358e7adf11b08
We call isRedirect to get the real language code instead of the site code.
Post-factum, lang attribute is added as well for each entry.
Bug: 53503
Change-Id: Ia6bf63a7cbe3c7b99ed05d0bd0fdd33190550c98
By passing in the information via a ResourceLoaderModule this
gets around any concerns with performance (version information
is read from the file system).
The version information is appended to the beta toolbar dialog.
Bug: 53050
Change-Id: I7836e1d4003416cbb7e18e3435aa87d82fd5c2e2
Also..
* removed an incorrrect comment referring to the old module
name (standalone didn't use the VisualEditorMessagesModule).
* made it use debug mode to determine whether to minify or
prettify the js code.
Change-Id: I493007649fba27e7faab0cf743eded5f68714c50
When a link was inserted, the cursor position was backwards (at the
beginning of the word rather than its end) - this commit fixes that
problem.
Also, thanks for the help Ed!
Bug: 53560
Change-Id: I04fe1ca4c9126898e7bf85cdf519794d66b4f38b
Also always use strings 'true'/'false' for the value, because
it is a string property (spellcheck, however, is a boolean)
and always use a capital second 'E' in the name.
Change-Id: Ia4e1f9edfd8f236fe81df190e6a68729d7b52243
The inspector popup should appear relative to the position of the related
calling method - either relative to the cursor (like in links and language)
or relative to the focusableNode (like in templates/transclusion).
Bug: 50905
Change-Id: I07f58d0c6561adecbec560fc24bcb6e590f2cd9f
This avoids problems when unnamed references were copy-pasted.
Knowing that key is always non-null simplifies a lot of logic
elsewhere.
Bug: 53365
Change-Id: I3a23123ae732d9583814d38dd880a0cdf691fd5d
Bug fix for browsers which don't have an event.clipboardData
property. The check is done correctly in onCopy but not onPaste.
Change-Id: I3cdf4c0358aa145dcb70c2c103d08a0002001fd4
This commit fixes two issues with insertion of annotations in blank space:
* LanguageInspector issue with inserting an language annotation inside any
whitespace (selection of space between words or collapsed selection in
blank line)
* AnnotationInspector issue with collapsed selection inside slugs. If
the marker was in a slug collapsed selection, activating
AnnotationInspector would expand the range to the closest word (on the
next paragraph). This commit makes sure the expansion for the next word
only happens if the selection is outside a slug.
Change-Id: I144eccefba16131a3d2ec6a3181adf47a15d6cc0
This listens to change events on the surface and checks to see if
there is more than just an empty paragraph node.
Bug: 53345
Change-Id: Ic8fa84d7cdcbffd154178939d0ec8c2c4f86c415
This functionality was (accidentally?) removed by I8f8a240a. It
stops us from over-zealously balancing data when we can get away
with just pasting the original selected range (e.g. it always wraps
collections of text and content nodes in another paragraph).
Bug: 53364
Change-Id: I93fa56c4e43083993c310e0050087e9d1de1e08b
modules/ve/ce/ve.ce.Surface.js
* Schedule the post-keypress async handler in a way that can be cancelled.
* Cancel it and run the handler immediately if another key event happens.
Bug: 53079
Change-Id: If139ff3230c10caa616743f71659c4606d290310
I claimed that it didn't preserve text nodes, but it does. It's just
that there's a bug where it doesn't preserve text nodes if the selector
passed to it is too simple, but 'link, meta, style' is complex enough
to avoid triggering this bug.
Change-Id: Id4a60dc87b8d4c613bc7013641b116dd7c331ac1
ce.AlienNode was mixing in GeneratedContentNode, but wasn't actually using
it properly. This commit fixes this so that AlienNode can benefit from
the <meta>/<link>/<style> stripping code in GeneratedContentNode.
Also added a getHashObject() function to dm.AlienNode to summarize the
domElements attribute because ve.getHash() chokes on it otherwise.
Change-Id: Ief3be94f9730297abe0e3c57506b81a8ff1d136d
There is no good reason why we'd render these tags, and their presence
causes Chrome to crash while cutting across them.
Bug: 50043
Change-Id: I611e3907cf20fa27dbef89ea941d0b787a44ba4f
Add a little robustness, guaranteeing that we don't end up with multiple
history tracking tasks running, leaking one, or try to clear a non-running
interval.
Change-Id: I41db2d6fefc7f45f150aa14ecefc648760ad6200
The selection property is never null; it is initialized to Range(0,0).
If it is set to null in purgeHistory(), the next call to
ve.dm.Surface.change() will crash.
Change-Id: Ia45c0ba26291e8ad09c445fdf2323710b5ab409f
domAttributeWhitelist wasn't actually being observed. Instead, we
already had the code in place to treat renderHtmlAttributes as a
boolean/whitelist/blacklist hybrid, it just wasn't used that way
yet.
This makes the interface nicer and fixes the bug where all attributes
(including data-parsoid and even things like onmouseover) were
rendered by CE.
Change-Id: I02e266c7c7dc197ed845164b7a705d786846a33b
If only a FocusableNode is selected the document doesn't have
real focus, so we must do it manually.
Bug: 53362
Change-Id: I781f59dda7f2884ff02f6688c2c8c037ac7ed1a6
* Assign cut/copy/paste events to the document so that
they are triggered when the CE doesn't have real focus
e.g. only a FocusableNode is selected
* Use clipboardData.setData when available. The key can
be stored and retrieved perfectly in text/xcustom but
this technique doesn't work in FF or IE
* Just use text content for key as this is what is written
to the clipboard, so this can be used directly without
having to get the content from the pasteTarget.
Bug: 48604
Bug: 49396
Change-Id: Ib3702f9441f6ee3fa34ec071f00994dd7e591d99
- Added missing @inheritdoc so that generated documentation is
not empty.
- Fixed type of mw.Platform#getMessage from (implied) @property
back to @method.
- Removed notes from mw methods. They are prepended instead of
appended, thus overriding the useful single-line summary
of the method with this random note. Description should either
be replaced entirely (e.g. no @inheritdoc) or inherited.
- Rephrased a few description to be consistent with the others
(e.g. "Get .." and "Add .." instead of "Gets .." or "Adds..").
Follows-up cbe35632f1.
Change-Id: Ie55bb9e18f1524b706f0e195300170e4d552bf73
The reversed image was created by Ebraminio using
convert loading.gif -flop loading2.gif
Bug: 51401
Change-Id: I264d9368cf8fd030ff34540e50e0038aa42ece16
Was previously broken as getSlice was using ve.Range#equals to
compare ranges which is direction-sensitive.
Bug: 51538
Change-Id: Ib58d1d8fd11b62388c111a5da66171d13a9db9c2
Objective:
* Use the MW link specifically, since the target/command system doesn't
understand the group/id/extension concept yet
Change-Id: I8b756fa0bb55468312bb30d45ac5b943ff7362b5
Currently ignores all non-element data, but element content (e.g.
images) can be annotated.
Added test cases and updated the test runner to only compare
store indexes for a more readable output.
Bug: 50127
Change-Id: I234586a28072811c8288aab56f6abaaa0da0c88d
Objectives:
* Make it possible to add items to toolbars without having to have all
toolbars know about the items in advance
* Make it possible to specialize an existing tool and have it be used
instead of the base implementation
Approach:
* Tools are named using a path-style category/id/ext system, making them
selectable, the latter component being used to differentiate extended
tools from their base classes, but is ignored during selection
* Toolbars have ToolGroups, which include or exclude tools by category or
category/id, and order them by promoting and demoting selections of
tools by category or category/id
Future:
* Add a way to place available but not yet placed tools in an "overflow"
group
* Add a mode to ToolGroup to make the tools a multi-column drop-down style
list with labels so tools with less obvious icons are easier to identify
- and probably use this as the overflow group
Change-Id: I7625f861435a99ce3d7a2b1ece9731aaab1776f8
Return an array of languages instead of a single language. Languages
containing hyphens return themselves along with the root code e.g.
'en-GB' => ['en-GB', 'en']
Change-Id: I840b689d0021d865f93d16d075473a2ed0a9f0d8
The old regex was lifted from PHP, which matches on UTF-8 byte sequences.
In PHP, [...\x80-\xFF]+ matches any bytes with the high bit set, which
by the particular properties of UTF-8 will match any sequence which
represents a Unicode character above U+007F.
In Javascript, regex matching is on UTF-16 Unicode code units, so we
don't have to do byte sequence matching (and cannot do so). So the
equivalent Javascript regex should use [...\u0080-\uFFFF]+, to match any
code unit above U+007F directly. (It also matches surrogate pairs, by
the particular properties of UTF-16, so any Unicode codepoint above
U+007F is matched).
Change-Id: I674b89f757b60331dd1cb23fd7ff8b18775012e9
Some browsers (e.g. Firefox) change the CE range when the dialog
is opened, so after the first surfaceModel change (to modify the
internal item) the surface's selection is modified, and the reference
is inserted in the wrong place.
Bug: 52159
Change-Id: Ia5da33b95a599ba78f308cf0554279ad44616f50
Problem: When the toolbar is created twice with the same config object,
the second time around the tools are still bound to the old surface
Reason: The tool config is overwritten such that symbolic names of tools
are replaced with instances of tools, bound to a specific surface. The
second time around, the creation fails (silently in a try-catch) and then
the already translated list of tools is used to create a new toolbar
filled with old tools still bound to the wrong surface.
Solution: Leave the config object alone, and instead build a new list of
tool instances while iterating through tool names.
Bonus: Don't fail silently. Using a try-catch to detect whether a
requested tool is supported masks other errors, and is evil. Instead,
just do a lookup and skip tools in which the lookup's result is falsey.
Change-Id: Ic43ec29173e556592bb3db9399ff83787e0a6857
toDataElement part fixed in I6d496f7. This fixes the
toDomElement part so we don't trigger a round trip warning.
Bug: 51963
Change-Id: I27a7579890d669a8b980710db1bafe066b744236
This isn't a problem when using the UI buttons as they get disabled
but the command keys can still trigger these methods.
Also fix hasPastState to include check for small stack. This fixes
an existing bug where the undo button doesn't become active until
~1s after the first change is commited (i.e. after the small stack
is committed to the big stack).
Bug: 52113
Change-Id: Idbd34953c805620881a609409290256462af80a5
This commit prepares the LanguageInputWidget to handle both annotation
and node, so it can be used as the GUI for both the LanguageInspector
and the LanguageBlockInspector that's coming up.
Cleaned up the way annotations are read into LanguageInspector and
AnnotationInspector. The attributes are kept in the Widget (without regard
to what datamodel they will serve) and are then read from the inspector.
The LinkInspector had to be adjusted slightly to accomodate a small change
in the AnnotationInspector too.
Change-Id: I17954707c00ffc4c32fbb44a6807a61760ad573c
The update event passes in a transaction object, which was interpreted
as a config object and fragmented the cache. Explicitly wrap the
update() call in an event handler to make sure the config parameter is
undefined.
Change-Id: I641c68230b92d23626fb8b12aeab6a8904a35bcc
This patch rounds off change I29740fa7a by replacing calls to EventLogging's
eventLog.logEvent with calls to VisualEditor's ve.track. ve.track publishes
events by providing an interface, ve.trackRegisterHandler, which event handlers
use to subscribe to VisualEditor events. By making it the responsibility of the
web analytics framework to register itself as a handler, VisualEditor can
remain decoupled from (and indeed ignorant of) any particular event logging
implementation. This allows VisualEditor to be integrated with many different
web analytics platforms with nothing more than a bit of glue code for mapping
ve's event semantics to those of the target platform.
The practical difference that this makes is that it frees VisualEditor from
having to know about EventLogging or from having to load EventLogging
components, which means we can remove quite a lot of gnarly code. My current
plan is to migrate the code for registering and loading the 'Edit'
schema module to Extension:CoreEvents, which is also where I'll commit the
handler for VE events. (CoreEvents exists precisely to provide an organized
place for persistent but WMF-particular instrumentation.)
Once this patch is merged and deployed, the following two configuration
variables may be removed from mediawiki-config:
- $wgVisualEditorEnableSplitTest
- $wgVisualEditorEnableEventLogging
Change-Id: Idfdf692668d2adfbe029e8f0c4ff9e96c60ff741
We were assuming images were wrapped in <a> tags. Images with
link='' are only <span> wrapped.
Bug: 51963
Change-Id: I6d496f719cfbbc7556c55f0a660cb192040f29de
Add rerender event to all image loads in MWExtensioNode.
MWHieroNode's implementation of onParseSuccess is now the same as
its parent so can be deleted.
Change-Id: Iaa4999372f1ba88a7bdf1490fc3f8640af77ceae
Create getter for extensionsName which is overriden by
MWAlienExtensionNode.
Also removed angle brackets around Alien title as the inspector
already has an angle bracket icon, and a '<' close button.
Change-Id: Ice8c5d73ed621f8e585b5f372788666f8c5aeb50
onUpdate was renamed to update. Also neither event was
actually implemented so have just removed them.
Change-Id: Iaae1661a99f97272fa42c71223fc2cb832d50c66
Previously we assumed that embedded icons mean we weren't
dealing with an inspector, but that is not always the case
(e.g. MWExtensionInspector).
Bug: 52845
Change-Id: Ifc5b054568661cb9badf6d7991f512b81e649b36
VisualEditor.i18n.php, VisualEditor.php
* Button title
* New experimental files
ve.*.MWAlienExtensionNode.js
* Very basic extension of ve.*.MWExtensionNode
ve.ui.MWAlienExtensionInspector.js
* Default to inline-block for wrapper. Should probably
get rid of styled wrappers for GeneratedContent eventually.
ve.ui.MWAlienExtensionInspector.js
* Basic extension of MWExtensionInspector. Override title to
use tag name e.g. '<easytimeline>'. Could be changed in future
to 'Extension: easytimeline' or similar.
*.png, *.svg, *Icons*.css, ve.ui.MWAlienExtensionButtonTool.js
* Angle bracket icon for button (open to suggestions)
ve.ui.MWInspector.css
* Make extension inspector text input tall by default.
Change-Id: I07f0686839192cad3cd8dfd3233ae907fe5cdf6a
Roan and I think this is way too light. The only way
I can tell it's a group is by mousing over all of
the icons back and forth really quickly :)
Increasing to 10% alpha.
Change-Id: Iab55bf64921de5247d10d611318e545efe74fe4a
GeneratedContentNode didn't track concurrent updates at all, so a
race condition was possible: if the node was updated a second time
before the first update had been rendered, the second update might
render first and then be overwritten by the other one.
To prevent this, we track the promise associated with the current
render. If a new update is launched while a previous one is still
pending we attempt to abort the old one by calling .abort() on it,
and ignore any future resolution or rejection from it.
Also allow rerenders based on non-model data by calling
.update( { config object } );
Change-Id: I8feefd9e8fb6c41d06b8b20131e3be5e37954e83
If you had an HTML element that was matched by two models, one with
a direct string match and one with a regex match, then the string
match would beat the regex match (which is correct) if they both
specified a tag name, but the regex match would win (which is wrong)
if they both didn't specify a tag name.
The fix is to only check for tagName === null if we're in tag-agnostic
mode (tag === '').
Change-Id: I9943611111e4c4ff498cdd95b7b3e72f95fb413b
Mostly as a demonstration of how easy this is with MWExtensionNode.
The icon was chosen with the following criteria:
1. Recognisable (the ankh is quite common in popular culture, right?)
2. Doesn't look idiotic to academics (I've consulted an Egyptology
PhD and they can confirm it's not the glyph for penis)
3. Renders well at <16x16
That said it does look a little like a stick man...
Bug: 43118
Change-Id: I9f9e8af501401866bfeecf0eec3690a705fbd4db
MWMath and other simple extensions all behave in a similar way, e.g.
<tagname>Foreign syntax</tagname>.
This creates a base class that should make supporting such extensions,
and editing their contents in a plain text box, very simple.
Change-Id: Icc0acb33fe32704f71dacb552d9dfa3142eaef2b
This allows abstract classes to specify RDFa types based on a static
property overridden by a child class. The default implementation is to
just use .static.matchRdfaTypes.
Change-Id: Ic71fc552a6a1626d94f998e9517af971e8198e79
Objectives:
* Use a class for toolbar groups to add more functionality later
* Rename addTools method to setup
Changes:
*.php
* Add link to new file
* Move ui element classes up for more general use
ve.init.mw.ViewPageTarget.js, ve.init.sa.Target.js, ve.ui.Context.js,
ve.ui.SurfaceWidget.js
* Update use of addTools method
ve.ui.Tool.css, ve.ui.Toolbar.css
* Move styles between sheets
ve.ui.Toolbar.js
* Rename addTools to setup
* Use ve.ui.ToolGroup objects when building tools
ve.ui.ToolGroup.js
* New class, encapsulates tools
Change-Id: Ic3a643634a80a8ac7d6f6f47f031d001c7efaee7
Objectives:
* Make drop down tools look more like buttons and less like inputs, since they aren't text input and are buttons
* Make context toolbars inside surface widgets render correctly
* Show outlines of groups on hover to hint tool relationships
* Make neighboring active tools look cleaner
Changes:
ve.ui.Tool.css
* Merge ButtonTool and DropdownTool styles as much as possible
* Add styles for DropdownTool active states
* Only round the corners of the first and last tool in a group
* Soften the borders between consecutive active tools
ve.ui.Toolbar.css
* Add border to groups on hover
ve.ui.Widget.css
* Isolate surface widget toolbar styles by using stricter selector
ve.ui.Tool.js
* Fix incorrect capitalization of class name
ve.ui.SurfaceWidget.js
* Add classes to toolbar and surface for better style targeting
Change-Id: Ib5ae8f705ef1e9c481e5bdf8c8dcef9c1eb22c4d
Objective:
* Remove ve.ui.DropdownTool's dependency on ve.ui.SurfaceToolbar so it
can be used with any ve.ui.Toolbar
Changes:
ve.ui.DropdownTool.js
* Bind onBlur to document mousedown in capture mode instead of trying to
add more and more things we are listening to which is a losing battle
* Refactor activate/deactivate mode changes
* Get rid of isEnabled check - surface should disable toolbar, the tools
shouldn't be checking if the surface is enabled after the fact (also,
this is harmless and doesn't change any actual interactions)
Change-Id: I738209d17649358c2f9812f9abac576960af867b
I trusted you guys when you told me to use DOM .focus() instead of
jQuery's .focus() and didn't test well enough :( The former doesn't
work, the latter does.
Follow-up to I7962f59b.
Bug: 47793
Change-Id: Iddfb8d7c99325b6c7a5d151948b57cfa5f0a6a62
This patch adds ve.track; it provides a means for VisualEditor code to log
various changes of state that are of potential analytic interest. This is done
without coupling VisualEditor to a particular analytics framework by providing
a method, ve.hook.registerHandler, by which event data may be routed to a
particular analytic framework for processing and dispatch.
ve.track uses a $.Callbacks-like object for tracking analytic events which can
remember an arbitrary number of past events. This is done by maintaining an
array containing the arguments of past calls and maintaining a counter for each
callback indicating its position in the queue (i.e., how many events it has
already received.) This ensures handlers are called for each event, including
events which were fired before the handler was registered. This allows the
load-order of VE and analytics components to remain unspecified.
Change-Id: I29740fa7a0ac403e484e0acee6dfcadaf6fc4566
See ApiVisualEditor.php#parsefragment.
Error code is also incorrectly about Parsoid, method
parseWikitextFragment does a FauxRequest to MediaWiki. Fixed
error.info. Keeping the same error.code for now for consistency.
Bug: 52483
Change-Id: Ic473ae4a5c1e9706140f6ec4cc8157fadd02c318
Objective:
* Make it possible to make a toolbar without a surface
Changes:
*.php
* Links to new file
ve.ui.Toolbar.js, ve.ui.SurfaceToolbar.js
* Split toolbar into generic and surface specific classes
*.js
* Update symbol names
Change-Id: Ice063a2fb67b5ce5155cdc96a0d47af49eee48cb
Follows-up ced2a8a which moved the tab layout to the server-side
and changed it to set up "source" tab and section links always
everywhere (even if VE would not be availabe in the namespace
or browser).
The JS logic (which continues to exist to take care of pages
cached before we moved it to PHP and/or to fix up pages cached
with a different configuration in the future) didn't do this yet
causing the "Edit source" tab to inconsistently appear on pages
for anonymous users viewing pages where VE is not available.
Change-Id: Ic575b3fcef17e636adaa338abc7748a4388ed9a9
This is bit of a hack, as leading whitespace could be
significant if styled with white-space:pre.
Long term VE shouldn't be editing the user's HTML, and
should just highlight potential formatting issues.
We avoid the stripping in preformatted elements as we
expect they will have that styling.
Bug: 51462
Change-Id: I654d98e17dd604cb2a192831ff3f3597f95b9962
Specifically: transclusions, formulae & references.
Captions also allowed to contain other images and reference lists
but we should probably not encourage that.
Change-Id: Ia1c99e51640a3f9ee53281a1e3ebd67dc13c8990
Because trying to work out how broken your test case is
by looking at two (potentially multi-page) serialisations
of the DOM summary is a pain in the arse. Diffing two
HTML strings may highlight the problem much more clearly.
TODO: Is it possible to defer the calculation of the HTML
infused summary object until we have determined the assertion
has failed. Otherwise we're slowing down our tests for no
reason.
Change-Id: I873bf2479ab81d15389792bd59d15580da63941a
Code speaks for itself, see also bug 52441.
Though not introduced by 14343c7bf7, that made the bug worse.
Bug: 52441
Change-Id: Ie2b80b22df03eb563de8812a47fb25152527e786
For configured wikis, show a dialog that welcomes the user to the
amazing and fantabulous world of VisualEditing, which is not only full of
wonderment and joy but also may lead to increased popularity and love.
The dialog only shows up once (uses a cookie).
Change-Id: I8e7c4dc2c63b36594378a543b9d66291395eebcf
* Generate the edit tabs and the section edit links in PHP, with a
fallback in JS for cases where we don't have them yet due to
caching. But only change things if VE is enabled, and have the JS
correct the state if the wrong cached HTML comes through.
* Make the order of the tabs/links and the messages to use as captions
configurable
* Make the edit tabs and section edit links always be present in the
page (regardless of namespace, user prefs, etc.) but be hidden and
have JS unhide them (using html.ve-available) if appropriate
* Add appendix messages so we can do a superscript "beta" even in places
where we can't use HTML in the message
VisualEditor.php:
* Add new hook registrations
* Remove edit link caption messages from the init init module because
they're now added dynamically in VisualEditor.hooks.php
* Add a noscript CSS module so we can hide some things in JS-less
environments
* Remove $wgVisualEditorTabLayout and replace it with
$wgVisualEditorPosition
* Add config vars for link captions, with null causing us to use
the default caption
* Add config vars for link caption appendices. Too many config vars
but we'll clean that up later
VisualEditor.hooks.php:
* Dynamically add tab messages to the init init module
* Remove unused globals in onBeforePageDisplay()
* Add noscript CSS module
* Add a SkinTemplateNavigation hook that changes and reorders the edit
tabs as appropriate
* Add a DoEditSectionLink hook that overwrites the edit section links
* Export the new config variables to JS
VisualEditor.i18n.php:
* Add beta appendix message
* Add a message for the default VE edit section link
ve.init.mw.ViewPageTarget.init.css:
* Remove the animation on the edit section links
* Darken the color of the brackets and the pipe from #ccc to #555
* Style the beta message to be superscript-like (but not real <sup> to
avoid moving the baseline)
ve.init.mw.ViewPageTarget.noscript.css:
* Hide the VE edit tab, the pipe and the VE edit section link initally
unless and until JS unhides
ve.init.mw.ViewPageTarget.init.js:
* Toggle .ve-not-available / .ve-available
* Edit tabs
** Only generate the the edit tabs if they're not already there from PHP
** Rewrite the edit tab generation to mirror what's being done in PHP
* Section edit links
** Same as for edit tabs
** Also add mw-visualeditor-expanded to pad the brackets
ve.init.mw.ViewPageTarget.js:
* #ca-ve-edit is now always the VE tab (and #ca-edit always the
edit source tab) so update the .selected behavior accordingly
Change-Id: Idcb15faea7fabe5fe7578b1508079969b27d2469
In some cases this would make VisualEditor be way too aggressive in
forcing you into the first matching page.
Bug: 52420
Change-Id: Ie0a793853d884ee0abf490a99c5214082e9dbf27
Added wgIsArticle to isViewPage checks, otherwise we were attempting
to load VE dynamically on Special:Move/Delete, which resulted in a
broken h1 title and odd behavior off the 'Read' tab.
Also added !wgIsArticle to pageExists. This is a bit of a hack because
we don't have any info on page existence in the JS on these pages
(I think?). But it's better to display 'Edit' for a page that doesn't
exist, than 'Create' for a page that does.
Bug: 49000
Change-Id: Ib47e5524d41e6066b362e0f5645750c769de5193
By testing against a regex of legal title characters we can determine
if the entered text is a valid internal link. If it isn't we should
prevent the link inpsector from creating/changing the annotation.
Bug: 33094
Change-Id: Ia1df602601e4e82fc351279e432c28c425f5157a
Not having a description yet is fine, but they should at least
be indexed as blocks so that they are searchable and listed
in the jsduck generated pages. jsduck defaults to @method + name
of prototype property. And it even guesses parameters sometimes.
Search: \n\n([a-zA-Z\.]+\.prototype\.[a-zA-Z]+)
Where: modules/ve,modules/ve-mw
Where-Not: modules/ve/test
Replace: \n\n/** */\n$1
Added @return in a few places where it was easy to add.
Change-Id: I830c94cc7dbc261bd7a077391f930cbfff165f9d
mw.ViewPageTarget is currently getting events from both the
platform target toolbar and context menu toolbar because the
event is emitted from within the toolbar to the surface.
Instead we're now emitting it on the toolbar itself and it is up
to the binder to access the correct one and listen to its events.
Bug: 52317
Change-Id: Ibd8053768e82b1df91081bd77a172628ea855db7
Follows-up 867ec44a9.
Because:
- #toolbarPosition is emitted more than once (so this
should at least have been a once() bind, not a connect)
- It is emitted for more than 1 toolbar (includes context menu
toolbar)
- Semantically incorrect (we want to know when the surface changes
not the toolbar)
- We want to get rid of that event entirely and this is the last
use of it.
Change-Id: Ica5ed04052f48fe84607abab72bcf65f97d689ed
Follows-up db3da5d. Also scanned code base for more matches but
looks like those have been cleaned up already.
Change-Id: I62d1c4367e1ed7b7162d7b688227dfa5dca562aa
Though this is already handled by Ie50b63ba5064e85d26 for the
server-side, and that should automatically reflect to the
client-side. Since we're dealing with cache conditions in
wmf-production where the user.options manifest does not yet
contain an entry for these relatively new preferences, lets
transfer the default value here as well. This does not affect
logged-in users (since their user options are always up-to-date
and embedded in the page).
Also made ve.support.es5 be casted to boolean. Previously it
would be a reference to JSON.stringify (if supported), or the
bottom value of whichever feature the browser didn't support.
Doesn't change any behaviour but should make things slightly
more performant when this value is evaluated.
Change-Id: I9ca430051ae6f4e603c2d89982e540e455055255
On browsers that implement the Navigation Timing API, performance.now()
provides values with microsecond precision that are guaranteed to be monotonic
(i.e., they are not subject to skew due to changes to the system clock).
This patch adds a `ve.now` utility function that will use this API when it is
available and fall back gracefully to `Date.now` when it is not.
Change-Id: I377025fcb23cb26399b9e437e33c8afa138916af
In target#setUpSurface, both target#setUpToolbar and
target.surface#initialize are called. #setUpToolbar does an
asynchronous animation.
After that animation is completed we call target.toolbar.initialize
and target.surface.context.update.
Right now ce.ProtectedNode needs to update the position of its
shields when the CE Surface changes position (which it does when
the UI Surface changes position because of the UI Toolbar changing
position), and does so by listening to toolbarPosition.
Adding this event to allow it to listen to that instead.
Change-Id: I826986794630c04c34cef6da36ccb15ff7dde49a
Formerly known as "The greatest commit in the history of the world*".
* Within a 3 block radius of Drayton Park and Auburt Park, starting
from July 30th at about 9pm or so.
Bugs:
* (bug 51404) Allow escaping out of the link inspector when in creation
mode (no text is selected, text will be inserted based on link target)
and the text input is empty
* (bug 51065 and bug 51415) Keep model and view in sync when changing the
link inspector's text input value and showing options in a menu
* (bug 51523) Either restore selection at the time of close to what it was
before opening the inspector (when using back) or to what it was before
closing (might be changed by transactions processed during the close
method) - this makes it simpler and more natural when clicking away from
the link inspector, even when there are changes that must be saved by
the link inspector on close
Bonus:
* Use only the light blue highlight color for menu widget items - the
checkmark already displays the selected item, the dark blue is just
masking the current highlight position and confusing the peoples
* Remove links when the user deletes everything from the link inspector's
text input and then closes the link inspector
* Replace select menu's evil "silent" selectItem/highlightItem argument
with a new method called initializeSelection which sets both selection
and highlighting to an item without emitting events - this is needed
when synchronizing the view with the model so the model isn't
immediately told to change to a value it already has
* Make the MWTitle lookup menu not flash like crazy as you type (this was
caused by a copy-paste oversight overriding
initializeLookupMenuSelection unnecessarily)
Bug: 51404
Bug: 51065
Bug: 51415
Bug: 51523
Change-Id: I339d9253ad472c2f42c3179edc84a83d27561270
The 'ext.visualEditor.genderSurvey' module was introduced in I2b4aba6a9
for the purpose of instrumenting a short-lived microsurvey that would be
concomitant with the deployment of VisualEditor. The survey has now run
its course; this patch removes its code.
Change-Id: I8be6198a66957d792757a5312e9e71b3c8cdd1e3
This code caught badtoken errors on load, but we can't get those
any more since the API module was split and we no longer send a token
on load. badtoken handling on save is done in mw.ViewPageTarget.
Bug: 51253
Change-Id: Idb172ee46b7142681d41e593eacd9600b8f11a9a
7557dd39ed make the badtoken handling code unreachable. Revert that
change, and fix the rest of the function to deal with the possibility
that editApi is undefined. Let handling of the read-only mode error
and any other errors fall through to the bottom of the function.
Change-Id: I0673f2bb629e5cc9449675c1074d283e3926e1d5
VisualEditor.php
* Add CSS file
ve.ce.MWMathNode.js
* Wrap the image in a span, so GenerateContentNode doesn't
try to nest an image inside an image
* Remove unnecessary attribute setting
* Only pass unwrapped image to deferred.resolve
* Retrigger MathJax rendering
ve.ce.Node.css
* Use inline-block for image wrapper
ve.dm.MWMathNode.js
* Mixin GeneratedContentNode and implement getHash
* Copy over functionality of MWTransclusionNode:
+ Just store data-mw for attributes
+ Store orignal(DomElement|MW|Index) for selser
ve.init.mw.ViewPageTarget.js
* Add mwMath to the toolbar
ve.ui.MWMathInspector.js
* Remove static.InputWidget, not required in this architecture
* Use multiline TextInputWidget
* Only update mw attribute
* Allow creation of new math nodes
ve.ui.MWInspector.css
* Set height of TextInputWidget
Change-Id: I520f8ccc9f89a2ce70aa1d9e02ed0c6cacbecc2f
It's totally unnecessary, and actually caused a bug where new references
got about="undefined", which caused Parsoid to about-group adjacent
new references together.
Bug: 52228
Change-Id: Id40d53c72a35412d612ae9441ae3d561622c1bec
When we encounter a ref tag inside the mw-data of a references
tag, we pass it off to the converter and store it as nested data.
In toDomElements we convert any nested children and write them
back to mw-data if changed.
As refs in references are invisible we exclude them when generating
the references list in ve.ce.MWReferenceListNode.
Bug: 51741
Change-Id: I31d06616849a00449df0fc77f3b33e46207cdc7f
op !== operation in all iterations of this loop except the first,
and using information from one operation to apply another one
doesn't work very well.
The fact that undefined cast to a number is NaN rather than 0
is very unhelpful :(
Also fixed some commas that should be semicolons.
Bug: 52238
Change-Id: I4138c023c955f2866881084506e24bb8b6db5a4d
Now Ctrl+\ (Cmd+\ on Mac) will trigger the 'clear annotations' button
on the current context. Ideally we'd also bond to the 'clear' keyboard
button (ASCII 12) but it does not seem possible to do that yet.
Bug: 51507
Change-Id: I300ec1ffa237e51418ec429be39001f820f053ae
== Renamed methods ==
* enableFloating -> enableFloatable
* disableFloating -> disableFloatable
* setPosition -> float
* resetPosition -> unfloat
== Scroll and resize event ==
Timeline for scroll event reduced from about half a dozen
"Recalculate style" and various forced "Paint" down to 0.
New timeline for scroll is clean (for me: from ~35 to ~59 fps):
* 1 Event (scroll)
* 1 Composite Layer
The composite layer action is the browser changing the viewport
to a different portion of the document drawing. Exactly the one
thing a simple scroll should do.
Timeline for resize event is still pretty crowded and low fps,
but it has improved. Further improvement would likely be around
using requestAnimation and going outside ve.ui.Toolbar.
== Changes ==
* New: ve.ui.Toolbar#initialize.
Similar to what surface has. Users of Toolbar should decide
whether to call enableFloatable, append it to the DOM at some
point and then call initialize() once.
* Don't compute offset() every time.
Eliminated by doing it once in #initialize. These 'top' and
'left' offsets do not change.
* Don't compute outerWidth() and $window.width() every time.
Reduced by doing it once in #initialize to compute the 'right'
offset. Updating it only on resize.
* Don't set 'top' every time.
This is already in the stylesheet. It was never set to anything
else so the abstraction for it in #float has been removed.
This also made it obvious that code for "ve-ui-toolbar-bottom"
was unused and left behind. Tha class was only ever being
removed from something (never added).
The one addClass call for it was in a condition that is always
false ("if top > 0").
* Don't set 'left' every time.
Eliminated by doing it once in #float.
* Don't set 'right' every time.
Reduced by no longer doing it on scroll. Done once in #float,
and on resize after computing the new value for it.
* Remove no-op style operations.
Wrapped methods in if-floatable, if-floated etc. to reduce a
fair amount of easily avoided re-paint overhead.
* Avoid double re-paint in mw.ViewPageTarget.
Though we prevent a lot of redundant re-paints now, whenever
we do repaint we want to do it in 1 repaint instead of 2.
ve.ui.Toolbar emits #toolbarPosition, which tells
mw.ViewPageTarget to update toolbarTracker which would read
the new $bar style properties and copy them over to the
$toolbarTracker. However, this read operation forces the browser
to do an immediate re-paint half-way just for $bar.
Browsers only repaint when style properties are changed and
JS has yielded. The exception to this is JS reading style
properties: in that case the browser is forced to do those
deferred repaints directly and reflect the new values.
We can avoid this double repaint by passing the updated values
as data instead of requiring the receiver to read the DOM (and
thus a keep the deferred repaint). Now toolbarTracker can use
them directly whilst the browser hasn't even repainted $bar yet.
== Clean up ==
* Redundant "border-radius: 0". This would reset something, but
it never does. None of the things it inherits from set a
border-radius. There is one subclass where toolbar is used
with a border-radius (".ve-ui-surfaceWidget .ve-ui-toolbar-bar"
sets a border-radius) which overrides this on purpose, so the
default of 0 is redundant.
* Pattern "if ( .. ) addClass() else removeClass()" changed to:
"toggleClass( , .. )"
Bug: 52014
Change-Id: I9be855148962eee068a77fe83e98eb20bbdcfeec
These have been pointing to the same method for a while now,
we can safely remove these obsolete aliases and just use it
as generic copy.
* Each file touched by my editor had its new line at EOF fixed
where absent
* Don't copy an otherwise unused empty object
(ve.dm.Converter)
* Use common ve#copy syntax instead to create a link
(ve.dm.Document, ve.dm.example)
* Remove redundant conditionals for isArray/copyArray/copyObject
(ve.dm.example)
Change-Id: If560e658dc1fb59bf01f702c97e3e82a50a8a255
The core changes to postedit in I778b18b that this depends on were
deployed to the cluster as part of 1.22wmf11.
Bug: 39632
Change-Id: Id4a8bc22c09a552ef79670b0d4fc4a70df07ec33
Opera 12 seems to work well enough, but I'm not confident enough to
whitelist it just yet.
Opera 15 is basically Chrome with a different interface, so it should
work perfectly, but it's barely out of beta and untested right now.
Bug: 36000
Change-Id: Ia80a6f53f8c128ef52d0bfde1828fdc132046afb
This is the language inspector UI engine with ULS core.
The Language Inspector works alongside ULS to choose and change language
blocks in text. The inspector was based on ve.ui.TextInputWidget and
now changed to inherit ve.ui.Widget and display details in a table
instead of an input textbox.
Added jQuery.ULS module:
* Repository: https://github.com/wikimedia/jquery.uls
* Latest Commit 728f112ffc90b03b50c0109487886a2647f12020
* Taken 'src' / 'images' and 'css' folders into modules/jquery.uls
Bug: 47759
Change-Id: I3c9fd6c135c05a54f6c7fc28c5962fc0a6677806
Annotations' attributes might contain DOM elements, which cause infinite
recursion in ve.compare(). Annotation classes can protect against this
by overriding getHashObject() to summarize DOM nodes, but that doesn't
help if that's not respected everywhere.
Instead, compare the hash objects, those are safe. This does not appear
to be a problem in practice, currently, because the nowiki annotation
is experimental, oo.compare() now short-circuits if a === b, and because
of optimizations in openAndCloseAnnotations() which lead to the relevant
compareToForSerialization() code path being taken very rarely.
Bug: 51948
Change-Id: If1bcc3eee4fd14d107db1935d89dcc5516643b53
This only affects debug mode, but things look broken when the
background of every single node is set to transparent (e.g. a
<pre> looks weird with a white instead of grey background).
It also leaves the DOM dirty full of inline styles.
Though setting a grey background isn't guaranteed to be visible
either, and all of these redraws and stuff really slow things
down (we should perhaps only start doing these after the initial
document is painted).. the least we can do is undo it and not
leave it there.
Change-Id: I9abfd46765914828ad8618748be5716a8c6b185c
By using annotation indexes only we can avoid a lot of
ve.getHash calls. This reduces the number of getHash calls
on load of [[:en:Argentina]] from ~60,000 to ~2,000.
Bug: 52013
Change-Id: I0bc9aa8feea5f7e4e90a5fcd829de57cab803c15
We would dirty-diff "</span>\n<!-- comment -->\n<span>" to
"</span>\n\n<!-- comment --><span>", i.e. the second newline made
a bunny-hop to the left over the comment.
The actual bug turned out to involve a double bunny-hop, with
"</span> <!-- comment -->\n<span>" turning into
"</span>\n <!--comment --><span>", i.e. the newline bunny-hops
both the comment and the space.
This happened because outputWrappedMetaItems() didn't take
wrappedWhitespace into account when restoring meta items and
associated whitespace. I hacked a check for wrappedWhitespace into it,
but we should really just rewrite this pile of hacks into a unified
system for queuing and processing both whitespace and metadata.
Change-Id: I4375f4c07983ffec6877d0371aeaa9bf6e65fd6e
To avoid confusion between IV store indexes and the index
within the set, rename them to storeIndex and offset.
Change-Id: Ic7d741bd5d39240d63fdc04a2df45658a64441de
As that method makes expensive ve.compare calls, we can quickly
avoid most cases by testing AnnotationSet#contains first.
On page load this reduces the number of ve.compare calls on
[[:en:Argentina]] from ~6,000,000 to about ~2,000.
Also reduces ve.compare calls per backspace keystroke from
~300 to 2.
We can optimise this further, but this is a good simple start.
Bug: 52013
Change-Id: Ie3b4517fd13383c48acb64b3c4e82051c34e7484
Previously, we'd clone the data but convert it in the context of
the existing dm.Document, whose nodes had pointers to elements in the
old data array, not to the cloned ones. Because dm.MWReferenceNode
has logic like if ( something === dataElement ), this caused the sanity
check conversion to behave slightly differently compared to the real
conversion that happens on save, and so a references corruption
bug went unnoticed.
Change-Id: I79a42ae21f91cb8eb410ae26ea638036db19e217
Pretty straightforward, although we should start thinking about
grouping/hiding 'advanced' formatting options in the toolbar.
Making this button experimental for now until we've come up with
a way to deal with this problem.
Bug: 51590
Change-Id: Ieb1935b742aced4b883d8a194e6cb69be68473d0
Server-side, plugins can register themselves by adding to
$wgVisualEditorPluginModules. This is the recommended way for
MW extensions to extend VE. Client-side, plugins can register
themselves through mw.libs.ve.addPlugin(), which takes a string
(RL module name) or a callback.
When VisualEditor loads, we load the registered plugin modules in
parallel with ext.visualEditor.core. Note that they're loaded in
parallel, not after, and so the plugins should explicitly depend
on ext.visualEditor.core if they use or extend classes in VE core.
Once the modules finish loading and user and site scripts have run,
we execute the registered plugin callbacks. These callbacks can
optionally return a promise. We gather these promises and wait for
all of them to be resolved, then initialize the editor.
This allows Gadgets to extend VE by top-loading a small module that
depends on ext.visualEditor.viewPageTarget.init and calls
mw.libs.ve.addPlugin( 'ext.gadget.bottomHalfGadget' ); , the bottom
half being a hidden Gadget that depends on ext.visualEditor.core and
contains the actual code. The addPlugin() call needs to be in a
top-loading module because otherwise there's no guarantee that the
plugin will be registered before the user clicks edit and VE loads.
User and site scripts can extend VE by simply calling addPlugin()
directly, as mw.libs.ve is already present when user scripts run (since
it's top-loaded) and VE waits for 'user' and 'site' to run before
executing plugins.
If user/site scripts need to load additional JS files, they can load
these with $.getScript() and return the corresponding promise:
mw.libs.ve.addPlugin( function() { return $.getScript( 'URL' ); } );
For a diagram of all this, see
https://www.mediawiki.org/wiki/File:VE-plugin-infrastructure.jpg :)
VisualEditor.php:
* Add $wgVisualEditorPluginModules
VisualEditor.hooks.php:
* Expose $wgVisualEditorPluginModules in JS
ve.init.mw.ViewPageTarget.init.js:
* Add mw.libs.ve.addPlugin function that just stores the registered
values in an array and passes them into the mw.Target when it's
being initialized
ve.init.mw.Target.js:
* Add $wgVisualEditorPluginModules to the set of modules to load when
initializing VE
* Add a Deferred (this.modulesReady) to track module loading
* Add addPlugin() and addPlugins() methods that add to either
this.modules or this.pluginCallbacks
* In load(), instead of mw.loader.load()ing this.modules, use using()
to load this.modules plus user and site, and fire onModulesReady()
when they're loaded
* In onModulesReady(), execute the registered callbacks, gather the
returned promises, wait for all of them to be resolved, then resolve
this.modulesReady
* Fire onReady based on this.modulesReady being resolved, rather than
using a second using() call
Bug: 50514
Change-Id: Ib7d87a17eaac6ecdb8b0803b13840d7ee58902df
Introduce method ve.ce.MWBlockImageNode.getCssClass and use it instead of
accessing ve.ce.MWBlockImageNode.static.cssClasses - it gives a better
way of handling special cases.
Bug: 51995
Change-Id: I236b08c8345a10d144f392ec37fd130cf5f7737d
If undoIndex is 0 then we don't need to do anything, or even
emit the history event which is quite expensive as it triggers
various node redraws.
Bug: 52012
Change-Id: I09ca2d6cd0f4cbaf8316819dab0bd6edfc5de62c
Whenever there is more than 2 spaces (except the extra space
on a continued line of an @ tag, or the extra space on a
continued line of a list item) it causes a <pre> context.
Removed both spurious spaces that caused a <pre> and ones that
didn't but looked like it could.
When making an ordered or unordered list, the first item needs
to be on a new line and in block context (e.g. an empty line
before it). Otherwise it is rendered inline as 1. Foo 2. Bar
(such as in #rebuildNodes where both the ordered and unordered
lists were broken).
Change-Id: Id0f154854afbdc8e5a8387da92e6b2cdf0875f69
The fix to the transclusion icon messed up the way inspectors appear in RTL
wikis. The rtl check/correction (inside 'this.embedded') seems to be the only
rtl fix necessary. Something completely different will have to be done to the
transclusion icon.
Change-Id: I2417e125c99de9b0c5fd922a47de43ed9952d6fd
If the first thing on the page is an image, then we'll try to select
it in Firefox, and get a JS error because .data( 'view' ) is undefined.
It turned out that MWBlockImageNode's onSetup() didn't call the parent
implementation, and all the way up in ve.ce.View.onSetup is where
we set .data( 'view' )
Bug: 51986
Change-Id: I0de3692566b0aa02a229054e07767e45fd5d4a49
* Give them a role=button, and a default tabIndex of 0
* Listen for a keypress of 'space' and emit a click event
(you'd have thought role=button would do this, but oh well)
Bug: 50047
Change-Id: I429ad165c95f34d26975daf81db18cc966802cde
We already correctly show the read only error if the user tries
to load VE which the database is locked, but if the database gets
locked after they've loaded VE, we also need to show the error
when they try to save.
Bug: 51636
Change-Id: I7a56f1b4387e7ea594a2a7f939c81626c9eee834
To achieve this we need to evaluate the DOM contents of
transclusion nodes to see if it consists solely of meta items
and whitespace.
To check for meta items we do a model registry match, but with an
additional parameter to exclude mwTransclusion types as a possible
result (as the first item may be a meta tag, but with a mw:Transclusion
typeof attribute).
Bug: 51322
Change-Id: I89a220350fb7e10e15f3682d21438539196a5846
For now this approach is bit of a hack and will hopefully
be replaced with an ability to cursor either side of an
annotation.
Bug: 51463
Change-Id: I701e3d26e06a28fed2d4950b1d418eda80a1fac5
EditPage has a lovely getCheckboxes() function which includes the
minor and watch checkboxes as rendered by MW core, as well as any
checkboxes extensions like FlaggedRevs might have added. Output
these in the API, render them, and send their values back.
ApiVisualEditor.php:
* Build a fake EditPage, get its checkboxes, and return them
ApiVisualEditorEdit.php:
* Pass through posted request data to ApiEdit, which passes it
through to EditPage thanks to Idab5b524b0e3 in core
ve.init.mw.ViewPageTarget.js:
* Remove minor and watch checkboxes from the save dialog template
and replace them with a generic checkbox container
* Have getSaveOptions() pull the state of all checkboxes in
** Special-case minor and watch, and pass the rest straight through
** Move normalization from true/false to presence/absence here, from
ve.init.mw.Target.prototype.save(), because here we know which ones
are checkboxes and we don't know that in save() without
special-casing
* Remove getSaveDialogHtml(), we don't need to hide checkboxes based on
rights anymore because in that case the API just won't send them to us.
** Moved logic for checking the watch checkbox down to where the same
logic for the minor checkbox already is
* Unwrap getSaveDialogHtml() in setupSaveDialog()
* Access minor and watch by their new IDs throughout
ve.init.mw.Target.js:
* Get and store checkboxes from the API
* Pass all keys straight through to the API
Bug: 49699
Change-Id: I09d02a42b05146bc9b7080ab38338ae869bf15e3
Previously it was faded out to 60%. contentSub contains FlaggedRevs
stuff we don't want around in the editor, and contains the revision
navigation when editing an oldid, which James decided also shouldn't
be visible when editing.
Change-Id: Icdef98f756ce92a32d276d6eeb22c9de04640d8b
Added GUI-level and Page-level "getDir()" methods to get the direction
of the GUI and Page respectively in the ve.ui.Surface and ve.ce.Surface
respectively.
The correction to the direction-test condition in ve.ui.Context reflects
the new method of getting these directions, and fixes the problem with
the transclusion icon. The icon position depends on the wiki/page-level
directionality, regardless of the GUI-level direction.
Bug: 51819
Change-Id: I36cef115017542c461e6d757f1c8bfda92074607
This preference will allow users to opt-out of VisualEditor during the beta
if they so choose. We do not re-use the alpha enablement flag because (a) this
would lead to a confusing preference description, and (b) because opting in
and then out of the alpha is not the same user choice as opting out of the
beta period.
Change-Id: I0f0a1b5eb21703ad422d007cab65c75ac1aa6fd8
This removes the initial alignment (either left or right) from new
inserted images, letting the wiki decide the default positioning.
Also, it makes sure that VisualEditor positions the image properly
(according to wiki defaults tright/tleft for ltr/rtl) when editing.
Bug: 51851
Change-Id: I25b966cf6f2736437509ea7e70bfda1bdbc79021
Flipped the generated positions of the MWCategoryPopupWidget and the
suggestion popup in the TextInputMenuWidget. The RTL position within
TextInputMenuWidget is only adjusted if the popup appears inside another
frame. This fix also corrects the suggestion popup positions in general
when inside another frame.
Bug: 51490
Bug: 51828
Change-Id: I83436d50a4a0596fdae9526c3fc2804cf880a530
Load the module always and have the conditionals on the
client-side so that we can change these without running into
problems with the new conditions not being rolled-out quickly
for anonymous users because the load queue is in the HTML
and cached for 30+ days.
This also allows us to fix above problem retroactively in wmf
production by just adding a mw.loader.load for this module
in something like MediaWiki:Common.js or something else that is
already in the cached load queue (temporarily, until the cache
has rolled over).
Removed unreachable code for loading ext.visualEditor.splitTest.
Change-Id: I21114960a88d224747447f2dc83d17d160f5f066
Opera triggers 'blur' on the document node when clicking on any <a>
link and never trigger 'focus' until after the user blurs the document
node *again* (by clicking outside of it or pressing 'Esc').
This causes the change polling to stop (SurfaceObserver#stop is called
without a subsequent call to SurfaceObserver#start).
To avoid this let's bind a delegated 'focus' event on all <a> links
inside the document and refocus it whenever that happens.
Bug: 47793
Change-Id: I7962f59bd02e075f91e42e6514b390c0d0feb3ab
Due to CSS specificity rules the styles defined for
.ve-ui-panelLayout-scrollable and .ve-ui-panelLayout-padded in
ve.ui.Layout.css were being overriden by more general rules for
.ve-ui-pagedDialog-pagesPanel .ve-ui-panelLayout in ve.ui.Dialog.css.
Bug: 51739
Change-Id: If2d5ec3168a874eb4f856450583d6c89967513df
* changes:
Add a node class for mw:Nowiki
Move getHashObject() from dm.Node up into dm.Model
Allow annotations to render nothing
Pass child DOM elements to annotations' toDomElements()
Process annotations bottom-up rather than top-down in data->DOM
Fixed two bugs found after merging:
1. Opened the Math node inspector without editing
anything, then clicked somewhere else on the page,
it crashed.
2. Similarly, opened the Math node inspector
without editing anything, then clicked the
"Cancel" button to cancel the edit, it crashed.
Both of these problems are fixed by this patch.
The issue was with using the getFocusedNode() in
the inspector onClose function to save changes.
Also, I included some minor changes relating to
the last code review. =D
Change-Id: I6e200f2a228b71dc5af5aa9843c461f43b926f8d
Refactor a few things to make it easier for scripts to see
not just whether mw.libs.ve is present but also whether it
allows the user to activate VisualEditor.
Change-Id: I50da8d9a260207d4ec1c43254dfe738f91386a9e
Adding the <code> element as a matched text style annotation, plus some
tests (for all the other un-tested text styles as well, whilst I'm at
it).
We'll need an icon, a button and a way of the buttons not forever
extending the length of the toolbar to properly edit <code> spans, but
this is a start.
Bonus: unit test coverage for all TextStyleAnnotations
Bug: 51590
Change-Id: I5438bcf2ec6eeb2e50400f8013964f91c33ce455