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