ve.ui.Inspector
* Removed disabled state and interfaces - this isn't needed
* Renamed prepareSelection to onInitialize
* Using event emitter to run onInitialize, onOpen and onClose methods
* Left removal up to the child class to handle in the onClose method
* Replaced calls on context to close inspector to calling close directly
* Renamed prepareSelection stub to onInitialize
* Emitting initialize event from within the open method
* Added recursion guarding to close method
* Changed the close method's argument to be remove instead of accept - the more common case is to save changes, and the only time you wouldn't save changes is if you were to remove the annotation
* Moved focus restore to close method
ve.ui.Context
* Moved the majority of the code in openInspector and closeInspector to event handlers for onInspectorOpen and onInspectorClose
* Updated calls to closeInspector re: accept->remove argument change
ve.ui.LinkInspector
* Renamed prepareSelection to onInitialize and rewrote logic and documentation
* Removed unused onLocationInputChange method
* Moved restore focus (now it's in the inspector base class)
ve.dm.SurfaceFragment
* Added word mode for expandRange
ve.dm.Surface
* Added locking/unlocking while processing transactions - this was not an issue before because this was effectively being done manually throughout ce (which needs to be cleaned up) but once we started using the content action to insert content dm and ce started playing off each other and inserting in a loop - we already do this for undo/redo so it makes sense to do it here as well
ve.InspectorAction
* Updated arguments re: close method's accept->remove argument change
Change-Id: I38995d4101fda71bfb2e6fe516603507ce820937
<span typeof="mw:Entity"> tags are now correctly represented in the
model, and rendered in CE. There are still issues with cursor movement
etc. in CE.
Because the prioritization mechanism for annotations vs nodes is broken
in the current "node API", I had to hack two special cases for mw:Entity
into the converter. I also had to change the converter to ignore the
children of inline nodes (this was a legitimate bug, but had never come
up before).
Change-Id: Ib9f70437c58b4ca06aa09f7272bf51d9c41b18f2
* Make converter generate meta nodes with 'style': 'comment'
* Handle style==='comment' in MetaBlockNode toDOM converter
* Add some comments to the meta test case
** Update other tests accordingly
* Change getDomElementSummary() to actually assert presence of comment
nodes (specifically, all non-text child nodes)
Change-Id: Ieef9418f4c47df3541477d9420aa2ab8df6e3df1
MWInternalLinkAnnotation was normalizing spaces to underscores. This is
bad. Instead, we now do the following:
* Normalize underscores to spaces for display purposes
* Store the original title without underscore/space mangling
* If the user didn't change the title (display title === original title
with s/_/ /g), use the original title. Otherwise use the user's title
verbatim, without normalizing either underscores or spaces.
Also, per a conversation with Gabriel, we now only restore hrefPrefix
when we're also restoring origTitle, otherwise Parsoid will barf.
Change-Id: Ia74a493b2bce96c9345b60ed692eeb2e43ebceff
When you leave the inspector by changing the selection, we need to apply changes to the old selection.
ve.ui.Inspector
* Added initialSelection
* Change getMatchingAnnotations to use a given fragment rather than generating it's own
* Set initialSelection on open
ve.ui.Context
* Make hiding the context accept changes
ve.ui.LinkInspector
* Passing a fragment into getMatchingAnnotations now
* Using fragment API instead of actions API to control the range of the fragment
Change-Id: If6c8845285d87d0f144b15d50c38e192c797be59
When the link inspector is used to create a new annotation, the text is annotated with the default link target derived from the selected text. Then if the inspector is used to change that value, yet another transaction is processed when the inspector is closed.
To avoid having to press undo 2x, this change makes the inspector undo it's first change before applying the changed annotation.
This change also introduces insert, remove and select content actions.
Change-Id: I3e29189158fb01336d6b053bc2a8bda2a91a0a46
AnnotationAction and SurfaceFragment now use insertAnnotations.
ve.dm.Surface.test
* Removed test for annotate method (not needed anymore)
ve.dm.SurfaceFragment
* Now using getInsertionAnnotations method
* Added support for modifying insertion annotations when annotating a zero-length selection
ve.dm.Surface
* Moved in insertion annotations state from document model
* Added insertion annotation interface (enable, disable, areEnabled, get, set, add, and remove)
* Simplified handling of annotations on change
* Removed annotate method (not used anymore)
ve.dm.Document
* Removed insertion annotations (moved it to surface model)
ve.ce.Surface
* Cleaned up handleInsertion and changed it to use the insertion annotations interface on the surface model
ve.AnnotationAction
* Moved insertion annotation handling out of here since it's now included in the surface fragment
Change-Id: I047d656acf7fa1c63f726ca2b0801e1476f84f96
ve.AnnotationAction
* Added filter to the clearAll method to allow clearing all matching annotations only
ve.dm.Document
* Some variable renaming for consistency
ve.dm.SurfaceFragment
* Added truncateRange method
* Added annotation scope to expandRange method
* Added support for passing an annotation object into annotateContent method
* Switched to using name instead of type in annotateContent method to match the ve.dm.Annotation class
* Fixed logic in annotation mode of expandSelection so that expansion only takes place if the annotation is found
ve.ui.LinkInspector
* Moved most of the functionality elsewhere
* General reorganization
* Changed setOverlayPosition to accept 2 arguments instead of an object with 2 properties and renamed it to positionOverlayBelow
* Check for annotation object before extracting target information from it
* Initialize default target as empty string to avoid undefined being cast to a string and the default target becoming 'undefined'
icons.ai, inspector.png, inspector.svg
* Added generic inspector icon which will be used when a custom icon is not specified in future inspector subclasses
ve.ui.Inspector.Icons
* Added inspector icon
* Renamed clear icon to remove to match it's actual image
ve.ui.Context
* Greatly simplified the interface, reducing the number of methods by inlining a few things and combining others
* Now always listening to resize events on the window rather than only while document is focused
* Not listening to scroll events anymore, they used to affect the top/bottom positioning of the menu which we don't do anymore
* Lots of cleanup and reorganization
* No need to fallback to empty array since getInspectorsForAnnotations does so already
* Only consider fully-covered annotations for inspectors
ve.ui.Frame
* Simplified the constructor by introducing the createFrame method
* General cleanup
* Typo fixes
ve.ui.Inspector
* Generalized lots of functionality previously located in the link inspector class which will be useful to all inspectors (such as title, clear button, saving changes, etc.)
* Added setDisabled and isDisabled methods to manage CSS changes and avoid needing to check the CSS to determine the state of the inspector (storing state in the view is evil)
* Added getMatchingAnnotations method for convenience
* Added prepareSelection stub
* Lots of cleanup and documentation
* Type pattern is now defined in base class
* Added stubs for onOpen and onClose with documentation so that subclass authors know what these methods do
* Removed checks for onOpen or onClose methods since they are now noop stubs and are always there
* Added stub and removed checks for onRemove
* Made esc key close and accept - the illusion is supposed to be that the link changes are applied instantly, even though they are only updated when you close, so all closing except for when removing should apply changes - i.e. esc is now equal to back rather than being a special function that doesn't have an associated affordance
* Only consider fully-covered annotations when getting matching annotations
ve.ui.InspectorFactory
* Depending on type pattern now since it's always there
* Added getInspectorsForAnnotations method
* Return empty array if annotation set is empty
VisualEditor, VisualEditor.i18n
* Added default inspector message
Change-Id: I1cc008445bcbc8cba6754ca4b6ac0397575980d5
TransactionProcessor was using parentOuterRange without checking whether
it was present, so it was exploding for indexInNode results.
Now checking for parentOuterRange presence, and falling back to
nodeOuterRange when missing.
This fix causes inconsistencies with zero-length text nodes. We should
fix these eventually, but for now I've just made the unit tests
tolerant of zero-length-text-node deviations.
Change-Id: Id9eadd57a0d5fcbaf009c0781da0a03928aebb31
Editing the text of a list item results in a change marker on the
paragraph within that list item. However, that paragraph usually isn't
present in the HTML, so the converter unwraps it when converting back to
HTML, and the change markers are lost. Instead, transfer the change
markers to the <li>.
Change-Id: Id675075d19c08d69bc8e990174841dc393b749fc
If the mouse is moved too quickly, the phantoms have a tendency to stick. This change moves the event from phantom.mouseleave to surface.mousemove.
Change-Id: I2c7e7bdc838427d4355a6c0c13bafe3198636dbe
This changeset introduces new variable property of ve.ce.Node called "live", which stores information whether or not given node is attached to the live DOM. When the value of this property changes event "live" is called.
Change-Id: I6d0ce923c25ff2c4015914f367582c9a15e62c65
jQuery.css('float') returns different null values for Chrome and Firefox. This fix takes this into account and applies shields only to aliens and floated descendants.
Change-Id: I4c1db148043ee95991a17720dee8febad62c415a
Native contenteditable execCommands were being tried before the surface was attached to the DOM. This is necessary for disabling native contenteditable object editing and resizing.
Change-Id: Idff6a30432396726deb8a38356172380ea12fced
We do not want to use the Feedback tool for the December release, as it does not
work cleanly with LiquidThreads and would strand most users in an unfamiliar
wiki and expect them to have more complex/technical responses than they are
likely to be able to give; instead, have just purged it entirely from the code
(except for i15d strings, per Roan).
Change-Id: Ieebdca3d365943d901e2df37228120fdcff50afd
* Factor out getHTML(), postHTML(), saveWikitext() and parseWikitext()
* Use the API to save instead of using doEdit() directly
** This fixes a lot of integration bugs
** Get rid of the blocked user check, edit API checks this
* Check the namespace parameter
* Require tokens and POST
* Add diff functionality
Change-Id: I31891d1485985629db4e39532fb34e0e7fe23796
Walk through node model attributes and pick just the HTML ones, then apply them to the DOM element
Change-Id: I7e0ffd71023ad692fcad7386b853410747398793
This changeset adds a visual treatment to uneditable AlienBlockNodes to indicate to the editor that the elements are uneditable. To deal with odd shapes, the alien's shields are cloned and added to a phantom container. The phantom container and the phantoms themselves may be styled appropriately.
Change-Id: I7ad52707966bc18be627aa4269725004edba86cd
ve.ce.getOffsetFromElementNode now supports adding outer length
of given node to status functions.
It is temporary solution that I will review in the future.
Change-Id: If779802156aa78dbced9d4c769e8e7877120b337
Browsers handle highlighting of our alien nodes differently. This change normalizes by hiding the native selection on the aliens, inserting blank image "shields" with native highlighting enabled.
Change-Id: Ica3576ef0e3c42b4aeae1da374cd1dc92f203d7d
When using jQuery insertBefore and insertAfter make sure to pass as a parameter jQuery selection of only one element (first for insertBefore and last for insertAfter).
Change-Id: Id469ed775642ab5be8e274ab3cb7730899e9487a
The signature of getUnlistRanges() changed in the UI rewrite, but the
recursive call wasn't updated. This caused unlisting of lists that
contain lists to break and throw a JS error.
Change-Id: I990120a906868a5160561cff6b963f5ba5473427
About groups are HTML structures like the following:
<div about="#mwt1">....</div>
<span about="#mwt1">...</span>
<div about="#mwt1">...</div>
When about groups are alienated, they are now merged into one alien
node, rather than producing a separate alien node for each sibling.
This is very basic about group handling, because it only works for
groups of directly adjacent siblings (text nodes are permitted in
between, but nothing else) assumes all about groups are aliens (which
is currently true).
* Before processing an element in the DOM->data converter, perform about
grouping on its children. This temporarily wraps about groups in
<div data-ve-aboutgroup="value of about attribute">
* Extended createAlien() to handle single nodes as well as wrappers
holding multiple nodes.
* In the data->DOM converter, temporarily wrap multi-node aliens in
<div data-ve-multi-child-alien-wrapper="true"> . This makes the rest
of the algorithm easier.
Change-Id: I2df5f62bc222b570fc11a89fe43d353f8363ead8
* Now ve.Factory inherits from the more general ve.Registry
* New class ve.CommandRegistry
* Refactored setupToolbar and command setup code into setupComands
Change-Id: Ic548e5de95b77889727362d3e66d7be83c12a603
The port of mousetrap wasn't really what we needed. This is much simpler, matches the rest of our code, and does exactly what we need.
Change-Id: I67f413e097fc2d4078336edb14dd9440e771f196
This fixes a problem with how Chrome renders native selection around floated elements. By adding pseudo elements before and after block aliens, the rendering is fixed.
Change-Id: I7fdbb8f4c42e29d0574b308b8c5740066bb58e94
Sequences that were scheduled directly after each other, such as "a b c" and "1 2 3" would end up overlapping sometimes, producing "a b 1 c 2 3" which failed to trigger the correct commands.
Change-Id: I27bb60e856e9d692a21e1587dc227f8aeb5fcf4e
This causes the converter not to strip inner whitespace in them, and
causes CE to suppress the whitespace mangling logic that is normally
applied (↵ for newlines, ➞ for tabs, alternating s for spaces).
Change-Id: I738a750c91a4ca4836c485e282865bb7525bf30a
* Add map of change markers per offset to Transaction
* Map is populated by TransactionProcessor
* Markers are reversed on rollback
* Removals aren't marked, Parsoid can detect these using DSR
discontinuities
Change-Id: I2290886ab411c6ad6162044ed85c091313613e51
* Added selectionStart and selectionEnd events to ve.ce.Surface
* Switched from debouncing model change events to just ignoring
model change events while the user is in selection mode
(dragging mouse or pressing shift+arrow keys)
* Fixed bug with callout appearing on resize.
Change-Id: I3bb9952867a983a4f7612964ff719a1179dd0fc6
* Remove VisualEditor namespace, and restrictions on it
** For MW.org these will be moved to mediawiki-config
* Add $wgVisualEditorNamespaces
* Add visualeditor-enable preference and respect it
* Use $skin->getTitle() rather than $wgTitle
* Remove "Sandbox" from i18n message
* Remove duplicate enforcement of VE namespace from JS
Change-Id: I956f68c2dde55e4063530fcc7c90eda048e0d78b
* Things broke when ve.ui stuff was refactored
* Save dialog is now completely stand-alone
This is an alterantive to Ib028e6967e8d2e158b05fd7582620c21cf9b85fb
which I believe is a better approach.
Change-Id: I7cb52d0750e859c4052e2008d929d197b88b9877
* ve.dm.Converter still generates metaInline/metaBlock elements as
before, it's not affected by this change
* ve.dm.Document constructor splits its input into "real" data and
metadata
** Metadata is stored in this.metadata (the meta-linmod) as a sparse
array of arrays, with an element for each offset in this.data
** this.data itself does not contain the metadata
** This means the node tree also doesn't contain the metadata
** Which means CE doesn't know about it at all
* All splice operations on the linear model are sent through
ve.dm.Document.spliceData(), which performs the splice and syncs the
meta-linmod
** Metadata in the removed range is reaped and added to the metadata for
the offset immediately following the removal
* ve.dm.Document.getFullData() splices the linmod and meta-linmod back
into each other; this "full data" is then fed back to ve.dm.Converter
Change-Id: Ief6dfd5b59cc13a8457993ed85c725413029c4fb
* Allow inspector to open with 0 length selection.
* Allow context menu to open with 0 length selection.
* Fixed bug in doc.getAnnotationsFromRange on zero length selection:
Method now returns annotations from start vs empty annotation set.
Change-Id: I3937c5c2824c7396d0c3ee11c13ffecdbed6052a
* Moved to tool specific configuration to static properties (left tool instance specific stuff in the constructors)
* Added documentation for tool configurations
* Centralized typePattern matching for inspectors
Change-Id: Ieacf61b320c10fd37ea69a05e543313fa990b403
* Actually return the spliced data like the docs claim we do
* Remove false claim that offset can be negative
* Add that data=[] && remove=0 is invalid; native splice() doesn't allow
this, and there is a case where we call native splice() directly
* Add tests
Change-Id: I90e77c1b22ea1c36cb61e89ea47831885a0b1cb9
Previously copyObject and copyArray would silently drop null values,
which is bad, especially considering we have example data for meta nodes
that has { 'key': null } somewhere.
Also added a test case that failed prior to this change.
Change-Id: I4f233cce041fbf38f701c494f1f78ac3d8535d88
Tests were completely broken because the link inspector threw a JS error
when trying to register itself with the nonexistent inspector factory.
Change-Id: I8a47222f0a5a37348262ed939b37fbc47d14e222
First stab at a simple command interface. This and commandFactory
will be refactored significantly before this code is put into
action.
Change-Id: I0de5d3271198c987baf06fb3011aebdc1671f498
* Rewrite of all tools, dramatically simplifiying them and decreasing
duplication
* Tools are now created using a tool factory instead of
a make-shift facility built into the toolbar
* All UI object have a surface or a toolbar reference instead of a
surface view
Change-Id: I589ecba36bf715b452d03c8fd5c0547dc3c1dc61
* Only show the inspector if the selected text has an inspectable annotation
* Replace the inline menu with a toolbar containing inspectable annotations
* Change the appearance of the inspector to match new mockups
* Add the trash can icon for removing annotations
* Move iframe handling code into a class that manages all that nonsense
Change-Id: I840f72426f9a9e50054a28de950393f0e9913153
Moved implementation of all the tools into a reusable action
system. To execute an action just call
surface.execute( actionName, method, param1, param2, ... );
This helps keep tools simple, and opens the door to key commands
reusing the same code.
Change-Id: Ie786fa3d38d1ea17d39b5dfb8eeeb5f2256267ce
Will be used by the history tools in a future commit, providing
a reasonable interface to this information rather than the tool
reaching into private members.
Change-Id: I0472349968e9b48ec17eb47b6845ec9ccf3811e2
Attempting to descend into a string or number would cause a JS error,
because we would attempt to create prop[arguments[i]] as an empty object
(which is ignored), then try to descend into it (which blows up because
it's undefined, even though we've just set it). Guard against this by
explicitly checking for non-object-ness.
Change-Id: Ie65550baaae0ab88476c9a1ff40cc136090740a0
* Adjust the range in the annotation synchronizer, otherwise we emit
events for the wrong node
* Expanded test suite to the point where it was able to catch the bug
caused by not adjusting annotated ranges
* Removed selection.length === 0 check, no longer needed because
selectNodes() now throws an exception in this case
* Added a FIXME comment about duplicate update events that occur when
length adjustments are combined with something else
* Add a few more comments
Change-Id: I84f0368b1d7b601ed0766806607152dc97f34603
* Lift node assignment out of the if/else
* Flip the condition so we detect text-only replacements rather than
non-text-only replacements
* Additionally assert that there is exactly one selected node, and that
it is a text node
Change-Id: Iaaddf532f06709e860ac44457470e6d8bfcb6dd9
* Store the applied state in the Transaction
* Store the Transaction in the TransactionProcessor (previously, only
its operations were stored)
* Have commit() and rollback() throw exceptions when passed transactions
with the wrong applied state
* Add tests for this behavior
Change-Id: I27b7a96fdf4d3555d78f64c05a03702ea560c802
The data array is now taken by reference, and the caller must perform
any copying required.
Changed tests to make a deep copy of shared data sets (mostly
ve.dm.example) before passing them to ve.dm.Document().
Change-Id: Iedc64f9fd9cd689640de9a19379cf5f3db94a2bb
There's no use case for keeping a deep copy of the 'internal' property
in the node tree, and it was breaking some of my new tests concerning
change markers. We could keep internal data in the node tree if we
wanted to, but to be correct we'd have to synchronize every time we
changed it, which is a pain.
Change-Id: I024de1ff8b6b6154da82c103c4bb21db8ff2ec14
Based on https://github.com/ccampbell/mousetrap.
Cleaned up to fit our coding standards, pass JSHint, and assume
jQuery's fixes where possible (e.g. no need for an addEvent
utility, no need for filling e.target, e.which, etc. cross-browser
which jQuery.Event already does).
Initially all were local functions in the constructor, but to
allow some customisations in subclasses moved various methods
to the prototype instead and marked with @private.
Really, only .register() must be called from the outside. The rest
assumes normalisation etc. or might break things if called
incorrectly.
Change-Id: Ic69a3c70759052094aefbeab623d885f8b118e14
This was only causing data bloat and also errors because htmlTagName and htmlAttributes are only set if the annotation was constructed from an HTML element
Change-Id: I3d36bca6cd0194e1a4456bb51156117f70b96b13
This is the outer range of the parent of the node, if known. We'll need
this for change marking: when resizing a text node, for instance, we
need to mark its containing parent. This way we get the containing
parent's element's offset for free (selectNodes already tracks it in
currentFrame) rather than having to compute it with another traversal.
Change-Id: Ia335d8080ea9d414ab9f89b943e2ea0cd11d7df3
Some tests were using the wrong node in the expected data, but because
only the summaries were compared, this would succeeed as long as the
type and length were equal (and paragraphs of length 1 are quite common
in our test data). Fixed equalNodeSelection() to compare each node by
reference as well as comparing the summaries. If one of the equality
tests fails, the summaries will still be displayed as expected/actual
data (even though they might be equal), and the message will have
"(reference equality for selection[3].node)" appended to it.
This change broke the tests because a few test cases had bad data, fixed
those in this commit as well.
Change-Id: Iab420cf29d47f7368c8a9ce79f6309efae75685c
For <p>1<br/>2</p>, selectNodes([2,2]) correctly returned the end of the
first text node, but selectNodes([4,4]) returned index 2 in the
paragraph (i.e. between the break node and the second text node). The
correct behavior is to return the start of the second text node, i.e.
the mirror image of the behavior for [2,2].
Fixed this by applying the startBetween/endBetween logic only if the
relevant adjacent node is wrapped (or if it's missing). In the code,
this is expressed as !(adjacent node present && adjacent node wrapped).
Change-Id: Ie3b7fdf1de38ee253a798a7a73bc89734f4ca4fa
The HTML "1<br/>2" was being converted to a linmod that looked like
"<p>1</p><br></br><p>2</p>". This commit fixes the wrapping logic such
that the result is "<p>1<br></br>2</p>" instead. In general, inline
nodes (content nodes) should not interrupt the wrapping, but block nodes
should.
This creates a problem for alien nodes: normally, we determine whether an
alien node is a block alien or an inline alien based on context, but if
we're in wrapping mode we're unsure of the context. We can't tell the
difference between "1<tt>Foo</tt>2" (should be wrapped as one, because
tt is inline) and "1<figure></figure>2" (1 and 2 should be wrapped
separately, because figure is block) using context alone, so in these
cases (and ONLY in these cases) we look up whether the HTML tag in
question is an inline tag or a block tag and use that to decide.
Change-Id: I75e7f3da387dd401d9b93e09a21751951eccbb83
* Added comments to classes and methods
* Quieted a jshint warning
* Broke some long lines
* Replaced instances of "var\t" with "var "
Change-Id: I1d617ed9e5180f1a3dff42078fb5debb5d718407
Firefox triggers a keypress event for backspace. We handle backspace in keydown, so this keypress event should be ignored.
Change-Id: I6a481dbd5df0cf4558a5f1975717ca809250ccda
* CenterNode missing in ResourceLoader registry
* UI classes and rangy not in static test/index.html
* Transaction and TransactionProcessor listed twice
Added a maintenance script that generates the <script> and <link> tags for all
files in the same order everywhere.
Change-Id: I5d22d33769b4e356e8065d295505f6f9a8b0bea8
If you select some text and start typing, we will now remove the content in the range and new content will be annotated with the annotations from the first character in the deleted range. This is similar to other editors.
Change-Id: I46ced52665ab10f9b724dbb225df5687c18a4c3a
Exception was caused by passing -1 to getAnnotationsFromOffset(). So
check for -1 before passing it in; getNearestContentOffset() can
legitimately return -1 if there are no content offsets in the document,
which occurs when the document is empty.
I was originally going to change getNearestContentOffset(start - 1, -1)
to getRelativeContentOffset(start, -1), but Inez correctly pointed out
that that would have unwanted results when near an inline node.
Change-Id: Ife4b497b1c5fd04d411bb25cea99e6ea2abf146f
This was reproducible by blanking the entire document (Ctrl+A Delete),
then undoing that (Ctrl+Z). AFAIK that's the only way to trigger an
insertion on a document that is completely empty.
Change-Id: I22252d5972a413dff614880a90c4c6b22e79672d
Also changed from using "type" to "name" to make it less specific and added a test to make sure it's working.
Change-Id: I150a7ab1a57b3df85b459dbc411c2eaefe08b5bb
The annotation-related code in the converter is greatly simplified
because the API itself takes care of almost everything already.
Change-Id: Ib48f52bad6b650a05dc4e7ef82db4158c19b3cf5
This changes ve.dm.LinkAnnotation to be a generic annotation for <a>
tags, and adds ve.dm.MWInternalLinkAnnotation and
ve.dm.MWExternalLinkAnnotation as MW-specific subclasses. This nicely
splits out the MW-specific parts in LinkAnnotation, and ideally we'd
also move these files somewhere else to reflect their MW-specificity,
but I haven't gotten to that yet.
Similarly, ve.dm.TextStyleAnnotation is now a generic base class for
simple tag-only-no-metadata annotations, and it has 11 subclasses, one
for each tag we support. This is quite a bit more verbose than the
previous code, but I think it's cleaner and more flexible. I considered
writing a function that would generate a TextStyleAnnotation subclass,
then calling that 11 times, but that's not possible if we want to keep
named functions for the constructors.
Change-Id: Ifba10153eef40280e44025dd72d4e9d9f33b0632
Fleshes out ve.dm.Annotation to a class. Annotations in the linear model
will be instances of a subclass of ve.dm.Annotation. Annotations are
defined by subclassing ve.dm.Annotation and registering this subclass
with ve.dm.AnnotationFactory.
ve.dm.AnnotationFactory keeps track of which annotation classes are known,
and has code to match an HTML element to an annotation class, for use in
the converter.
Change-Id: I68802bdb8736ced1f9e04ee49c623944b448141c
The cursor will move natively when it can, allowing for word jumping with alt/ctrl keys. Special conditions exist for slugs and node boundaries that result in programatic movement.
Change-Id: Ife156bf94d8192ddd322c016ca8359855b17d7fc
Removing check for insertAnnotations length because it's also important to know if we're pre-unannotating text.
Change-Id: I7fab39ca353d7656de3ce2985a821cb54384100e
Utility function to generate an opening HTML tag. Needed to integrate
the new annotation API with ve.ce.TextNode
Change-Id: I6804bbf6f79346fde1887fa82d29ec5cd0342d60
Previously, Undo used a transaction's lengthDifference to calculate the selection to display after the transaction was undone. Now, translateOffset with the reversed boolean set to true will properly translate the inverse of a transaction's selection change. Fixes bug #40538
Change-Id: I110bc0cbb5824547842efd391b9f2948b037b758
We were populating empty content nodes with zero-length text nodes to
make round-trip tests in the test suite work (otherwise blanking a
paragraph leaves behind a zero-length text node whereas creating an
empty paragraph does not), but the empty nodes are causing problems in
CE apparently.
* Do not create empty text nodes when constructing a node tree
* Be more careful with text-only replacements:
** Don't resize a text node to zero, remove it instead
** There may not be a text node to resize at all, build it in that case
** Switch nodeRange to nodeOuterRange, this was probably broken before
Tests:
* Change test case for zero-length text node to assert that there is
*no* zero-length text node :)
* Remove a test case concerning an empty text node from the
ve.ce.TextNode suite
Change-Id: Ie677457f2f0a7823a517ba3077b844ef52a20fcc
Previously tests for inheritClass (and other object management
utilities) were absent (as they were copied from upstream K-js).
I've copied the upstream test suite for this method here and
extended it with tests for this new feature.
Had to add es5:true to .jshintrc due to a bug in JSHint.
Repeated the setting in ve.inheritClass for future reference.
Source: https://github.com/Krinkle/K-js/blob/master/test/K.test.js
Change-Id: I63ac620d6ce7832ebfee454ddf7b7c90f6eb6121
This works just fine, as also previously tested/proven by
ve.cloneObject, which uses the same concept of creating an object
identical to what invoking the constructor with "new" would do,
but without invoking the constructor function (which has side-
effects).
Except in this case we do invoke the constructor function, but
we can't use new in ve.Factory because of the arbitrary number of
arguments.
Added a test to assert that 3+ arguments and that instanceof
work as expected.
Change-Id: If0add3da7475886e476900044acda2ba7d01fb11
Add some missing constructor names and rename the ones with a
lowercase 'v'.
I previously changed Object.create and others to using hasOwn,
but that turned out to be useless. The thought at the time was
to only use the native one if it really is a native one (and not
a polyfill from another script), however in then hasOwn is only
relevant on prototypes and when negated. For static members it
would be an own-property either way.
Follows-up:
* Id6783fcfc35a896db088ff424ff9faaabcaff716 (metanode)
* Iab763954fb8cf375900d7a9a92dec1c755d5407e (object-management)
Change-Id: Ia6ef597e5e5453277472dfc23f25d2878b68b7f6
I think what happened here is I added the skeleton code, Kranitor came through and removed the unused arguments, then I merged in my implementations without pulling, then pushed - git merged cleanly, the arguments I thought were there were not there, and tests broke.
Change-Id: I5aa2968fef164c774a10db83a6df1753c93cd2dc
Specifically, go to [[mw:VisualEditor/Feedback]] rather than [[mw:Visual editor/
Feedback]], as the primary set of pages on MWwiki have been moved some time ago
and right now we're stranding users' feedback messages at the wrong place.
Change-Id: Ia2ba0dad7d1bf0d1633fe2704a2e8354285c66da
This allowed me to move ve.ce.Surface particulars (such as the starting, stopping and clearing of polling) out of the UI code.
Also cleaned up some switch statements.
Change-Id: I7b85e42a4e01f8d76237d995e25275f2424541ea
Previously, we were looking one offset to the left to load the insertAnnotations. This would fail at the beginning of a document that began with a slug, and probably other cases too. Now using getRelativeContent offset.
Change-Id: I31b24e2ccfa9fda2ce7fb19d1221f8708a96083f
Slugs aren't represented in the model at all, but in the DOM they do
contain a single character ( or ), so we have to override
the return value of getDomText() to be empty.
Change-Id: Ic93cb694b0632bc81d8d0749149e4d739232ed48
Iterating forwards while removing from an array is a good way to get half way there and be confused as hell.
Change-Id: I74db84eee87c73d8e035f6dc8a92be0d0b9b3dad
* Added some new icons (to be used soon in the inspector redesign)
* Added right-to-left icons for lists
* Renamed some icons for future RTL use
Change-Id: I10e3e3fcda82786e3064176e7eefe211b88db95c
Was cloning the original set, then adding to it - resulting in always containing the whole set in any match.
Also using test instead of exec since exec returns a string result, which under strange circumstances could return a falsy result, despite the RegExp finding a match.
Change-Id: I09a7cb264521d58f02d6ff2547edad9a740b23b2
Surface model annotate method previously cleared basic tool annotation objects.
Now that bold and other annotations have htmlAttributes from parsoid,
we must gather annotations by type from selection and iterate through
to properly clear.
Change-Id: Id53bf5733078524ae5aac376e01b9679eb8c32df
Rather than each tool requesting annotations, and nodes pertaining to selection,
Emitted event supplies annotations and nodes to each tool's update method.
Using select vs. of traverseLeafNodes for code optimization.
Better documentation for updateTools()
Removed unneeded code.
Change-Id: I7c0baa1cc0f7fb731d6e28b175a76e931e9e2961
* Added documentation for ve.AnnotationSet
* Replaced uses of "// Inheritance" with "// parent Constructor"
* Added "// Mixin constructor" where needed
* Added missing section comments like "/* Static Methods */"
* Cleaned up excessive newlines (matching /\n\n\n/g)
* Put unnecessarily multi-line statements on a single line
Change-Id: I2c9b47ba296f7dd3c9cc2985581fbcefd6d76325
* Commands for Sublime:
Find*: "(\* @[a-z]+) ([^{].*) \{(.*)\}"
Replace: "$1 {$3} $2"
Save all && Close all
Find: " function("
Replace: " function ("
Save all && Close all
Find: "Intialization"
Replace: "Initialization"
Save all && Close all
* Consistent use of types (documented in CODING.rm):
- Merged {Integer} into {Number}.
- Merged {DOM Node} into {DOMElement}.
* Remove work-around /*jshint newcap: false */ from ve.js
Calling Object() as a function to to use the internal
toObject no longer throws a newcap warning in JSHint.
It only does that normal functions now .
(e.g. var a = Cap(); or var a = new uncap();)
* Add missing annotations (@static, @method, ..).
* Remove unused variables
* Remove null-assignments to variables that should just be
undefined. There's a few variables explicitly set to null
whereas they are set a few lines under and not used otherwise
(e.g. 'tx' in ve.ce.Surface.prototype.onPaste)
Change-Id: I0721a08f8ecd93c25595aedaa1aadb0e08b83799
Detecting page status in a similar way as WikiEditor inspector.
Disabled accept button now behaves appropriately.
Accept button status is now evaluated on enter or submit.
Change-Id: Ibfef6ffd87cb9a71e37242d6214d0f8e3af2e2c0
This node type represents <meta> or <link> (transparently, based on the
style attribute). I had to make two node types for this and hack the
toData conversion code directly into ve.dm.Converter, because we don't
have native support for node types that can be both inline and block.
(We should add this in the node API rewrite.)
The CE implementation renders a placeholder (with the same styles as an
alien node) right now. I'm not sure how nice that is, but it's better
than rendering raw <meta>/<link> tags.
This whole thing is a total pile of hacks to make VE deal with
<meta>/<link> tags until we have a proper node types API.
Change-Id: Id6783fcfc35a896db088ff424ff9faaabcaff716
Icon appears when scrolling and resizing window.
Instead of always setting the context on scroll and resize, bind to the
updateContextIcon method.
Icon appears when selecting a non content data offset.
Changed logic to show icon changed to content length vs range difference.
Move Link inspector getSelectionText to ve.dm.document getText.
Rationale, more bits of the code depend on evaluating content.
Added new ve.Range truncate method.
Remove getSelectionText, using truncate range & document.getText instead.
Change-Id: Ibd3e99c923f18d2c96a86d92e74e2e9ebd49c85f
This was broken in three different ways:
* On the way in, we were applying whitespace to an array of elements
rather than the actual element, so the whitespace wasn't stored.
* Whitespace processing on the way out was skipped for aliens because
they had their own code path. Refactored this so alien openings and
regular openings share much more code, including whitespace output.
* Somewhat unrelatedly, innerPost output was broken for paragraphs
containing inline elements, because the inline elements' processing
polluted lastOuterPost. Discovered this because my test with inline
aliens also happened to be the first test of whitespace preservation
in paragraphs with inline content elements. Fixed by explicitly
skipping content nodes when outputting whitespace.
Fixed these issues and added a test case.
Change-Id: I8edb61a008e60ace886b1a841b3417682ec39c32
* For the most common case:
- replace ve.extendClass with ve.inheritClass (chose slightly
different names to detect usage of the old/new one, and I
like 'inherit' better).
- move it up to below the constructor, see doc block for why.
* Cases where more than 2 arguments were passed to
ve.extendClass are handled differently depending on the case.
In case of a longer inheritance tree, the other arguments
could be omitted (like in "ve.ce.FooBar, ve.FooBar,
ve.Bar". ve.ce.FooBar only needs to inherit from ve.FooBar,
because ve.ce.FooBar inherits from ve.Bar).
In the case of where it previously had two mixins with
ve.extendClass(), either one becomes inheritClass and one
a mixin, both to mixinClass().
No visible changes should come from this commit as the
instances still all have the same visible properties in the
end. No more or less than before.
* Misc.:
- Be consistent in calling parent constructors in the
same order as the inheritance.
- Add missing @extends and @param documentation.
- Replace invalid {Integer} type hint with {Number}.
- Consistent doc comments order:
@class, @abstract, @constructor, @extends, @params.
- Fix indentation errors
A fairly common mistake was a superfluous space before the
identifier on the assignment line directly below the
documentation comment.
$ ack "^ [^*]" --js modules/ve
- Typo "Inhertiance" -> "Inheritance".
- Replacing the other confusing comment "Inheritance" (inside
the constructor) with "Parent constructor".
- Add missing @abstract for ve.ui.Tool.
- Corrected ve.FormatDropdownTool to ve.ui.FormatDropdownTool.js
- Add function names to all @constructor functions. Now that we
have inheritance it is important and useful to have these
functions not be anonymous.
Example of debug shot: http://cl.ly/image/1j3c160w3D45
Makes the difference between
< documentNode;
> ve_dm_DocumentNode
...
: ve_dm_BranchNode
...
: ve_dm_Node
...
: ve_dm_Node
...
: Object
...
without names (current situation):
< documentNode;
> Object
...
: Object
...
: Object
...
: Object
...
: Object
...
though before this commit, it really looks like this
(flattened since ve.extendClass really did a mixin):
< documentNode;
> Object
...
...
...
Pattern in Sublime (case-sensitive) to find nameless
constructor functions:
"^ve\..*\.([A-Z])([^\.]+) = function \("
Change-Id: Iab763954fb8cf375900d7a9a92dec1c755d5407e
In preparation of pushing the object-management branch, which
will need more shared variables (for efficiency) creating
a shared closure. To avoid a spegetti of immediately-invoked
functions that return functions (like ve.getObjectValues and
ve.getObjectKeys).
Less duplication of code and faster execution.
First I had the closure around it as-is but then I figured it'd
be faster to have a local reference to ve (instead of having to
go through implied globals for references to other ve.*)
So I made it a local variable and then exposed it. That way
anything inside referring to each other stays within the same
scope.
Review with ignore-whitespace for clarity.
Change-Id: I415d8635db6d82cf239f0364ccc2d63a61bd5a6d
Introduced the ve.AnnotationSet class to manage sets of annotations. This
is a generalization of ve.OrderedHashSet, a class that manages a set
using an array and an object keyed by hash.
Converted everything that stores, tracks or passes around annotations to
use ve.AnnotationSet. In particular, this means the linear model now
contains AnnotationSets instead of hash-keyed objects.
This allows us to maintain the order of annotations in the linear model,
and will help fix bugs with annotation ordering and splitting.
Change-Id: I50975b0a95f4cc33017a0b59fdede9ed1eff0124
Currently this is done in a hacky way because we don't have a real
registry of RDFa types for node types, so we just hardcode the list of
recognized types (only links currently).
Change-Id: I5afcc55701fc6fa0ee2a360dcf5ca62b065292f5
* Also clean up ve.init.mw.ViewPageTarget...setupSaveDialog
Consistently use viewPage instead of 'this' inside this
function. The reason it is locally aliased is because there is
other 'this'es used here. Using them mixed is even more
confusing.
- No need for ve.bind, other handlers in this function also
just use viewPage instead of binding this.
Change-Id: I25e93862a39134961bf80835f46cbf531d8109e0
[jshint]
ce/ve.ce.Surface.js: line 670, col 9, Too many var statements.
ce/ve.ce.Surface.js: line 695, col 6, Missing semicolon.
ce/ve.ce.Surface.js: line 726, col 22, Expected '===' and instead saw '=='.
ce/ve.ce.Surface.js: line 726, col 41, Expected '===' and instead saw '=='.
ce/ve.ce.Surface.js: line 733, col 13, Too many var statements.
ce/ve.ce.Surface.js: line 734, col 24, Expected '===' and instead saw '=='.
ce/ve.ce.Surface.js: line 1013, col 13, Too many var statements.
ce/ve.ce.Surface.js: line 1019, col 17, Too many var statements.
ce/ve.ce.Surface.js: line 1023, col 18, Too many ar statements.
ce/ve.ce.Surface.js: line 1027, col 13, Too many var statements.
dm/annotations/ve.dm.LinkAnnotation.js: line 70, col 52, Insecure '.'.
dm/ve.dm.Converter.js: line 383, col 29, Empty block.
dm/ve.dm.Converter.js: line 423, col 33, Empty block.
Commands:
* jshint .
* ack '(if|else|function|switch|for|while)\('
* Sublime Text 2:
Find(*): (if|else|function|switch|for|while)\(
Replace: $1 (
* ack ' ' -Q # double spaces, except in certain comments
Change-Id: I8e34bf2924bc8688fdf8acef08bbc4f6707e93be
MultiSuggest:
Added CSS Ellipsis config option which provides CSS to suggestion items.
LinkInspector:
-Configured multiSuggest for page suggestions with CSS ellipsis off and removed CSS definitions.
Instead, using jquery.autoEllpisis plugin for centered position ellipsis. (Bug 39591)
-Temporary tweak to link input padding to prevent text from overlapping down arrow.
Down arrow soon to be implemented differently.
RTL Fixes:
-MultiSuggest overlay positions correctly by setting a width.
-MultiSuggest background image position fix.
Change-Id: I806ead5a2c2621589f76cfb2b03805cbd0b0a18a
* Moved icons into Illustrator (used to be in Photoshop)
* Added SVG icons too
* Added support for devices with pixel ratio > 1 (they use SVG)
* Cleaned up icons (little rendering errors here and there)
* Organized icons into their own folder
* Increased the horizontal margin of the down arrows in the formatting (in the toolbar) and location (in the link inspector) drop down menus
Change-Id: I29b7084c9b1145051b2a76f514cfca9826d53ddb
This will cause ve.dm.SurfaceFragment.prototype.insertContent() to place
the selection after the insertion as well.
Change-Id: Ifa7e627daceb90408422eb58c110d475f34ba1e2
* Separated DOM changes from creation of elements
* Always using parsing for element creation with known attributes
* Always using attr or addClass for variable attributes
Change-Id: Id101f56594014786892d382d06c658f416224a9c
* Switched a lot of classes from es-* to ve-ui-*
* Removed all the DOM structure left over from the old sandbox demo
* Got rid of transparent backgrounds
* Added menu font-size rule to stand-alone target
* Moved some rules around that were in the wrong places
* Got rid of some unused/unneeded methods in the mw target (attach and detach surface methods)
* Added active class to context icon with shallower shadow effect so it doesn't break your spacial perception when you click on it
* Renamed the iframe and iframe wrapper elements so it's easier to see where they came from
* Removed unused CSS rules
* Fixed some uses of prop( 'class', … ) to addClass
Change-Id: I54a660ca0baf0baa4463faca7a1edcf648130b6b
* function() -> function ()
* ){ -> ) {
* Quoted JSON keys (Look the other way Timo!)
* Using more descriptive group names, which also avoid using "new" as a key
* Line breaks at 100 columns using 4 spaces/tab
* Not setting classes on suggestion items that have no effect (such as 'external' on a div - even on an <a> tag this isn't enough to get the style because it's not inside #content)
Change-Id: I37032fa8ba93adb7b719d9797f9b1b806359cc13
* Replaces c8b4a28936
* Use Object() casting to detect objects instead of .constructor
(or instanceof). Both .constructor and instanceof compare by reference
the type "Object" which means if the object comes from another window
(where there is a different "Object" and "Object.prototype") it will
drop out of the system and go freewack.
Theory: If a variable casted to an object returns true when strictly compared
to the original, the input must be an object.
Which is true. It doesn't change the inheritance, it doesn't make it inherit
from this window's Object if the object is from another window's object. All it
does is cast to an object if not an object already.
So e.g. "Object(5) !== 5" because 5 is a primitive value as opposed to an instance
of Number.
And contrary to "typeof", it doesn't return true for "null".
* .constructor also has the problem that it only works this way if the
input is a plain object. e.g. a simple construtor function that creates
an object also get in the wrong side of the if/else case since it is
an instance of Object, but not directly (rather indirectly via another
constructor).
* Added unit tests for basic getHash usage, as well as regression tests
against the above two mentioned problems (these tests fail before this commit).
* While at it, also improved other utilities a bit.
- Use hasOwnProperty instead of casting to boolean
when checking for presence of native support.
Thanks to Douglas Crockford for that tip.
- Fix documentation for ve.getHash: Parameter is not named "obj".
- Add Object-check to ve.getObjectKeys per ES5 Object.keys spec (to match native behavior)
- Add Object-check to ve.getObjectValues to match ve.getObjectKeys
- Improved performance of ve.getObjectKeys shim. Tried several potential optimizations
and compared with jsperf. Using a "static" reference to hasOwn improves performance
(by not having to look it up 4 scopes up and 3 property levels deep).
Also using [.length] instead of .push() shared off a few ms.
- Added unit tests for ve.getObjectValues
Change-Id: If24d09405321f201c67f7df75d332bb1171c8a36
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
Pressing enter in an empty last list item should remove the list item and add a paragraph. Transaction was not being committed.
Change-Id: I0b173125d48f629eab923e051648d2036bb8956c
In current implementation ve.ce.TextNode can be represented by more then one DOM node (TEXT_NODE and or ELEMENT_NODE) - for instance "Lorem <b>Ipsum</b> est" (TEXT, ELEMENT, TEXT).
Change-Id: I6530cbf1273ad1b1de3599c3eb929eb7abc2d59e
* Added oldid param to the API
* Added oldId argument to ve.init.mw.ViewPageTarget
* Added redirect when saving an oldid page (which adds a new revision)
* Added venotify param to allow notifications even when redirected
* Added creation notification
* Added page title to saved/created notification
Change-Id: I9e957e6f5bc7920093481ffe3c33e299f87ce50a
Got rid of some commented out code we aren't going to use and fixed the order of arguments to background position to x, y
Change-Id: I4e638c33b053dd916681dc91c8c0d7cff224375d
* Added style for monobook
* Added monobook to whitelisted skins
* Made ve.init.mw.ViewPageTarget resilliant to vector and monobook-like skins
Change-Id: Ia39e034229204ae5f1f70dce5d74c6c4db42277b
data-mw-gc is ancient and unused. We do need to detect and alienate
generated nodes, but that is now based on RDFa types. Removing the
data-mw-gc stuff for now because it doesn't work anyway, will replace it
with proper detection later.
Replaced instances of data-mw-gc in the test suite with unregistered
node types.
Change-Id: If3f5898d382a436fa57929013264c53af5e840ba
* Added more support for making dynamic skin changes in vector (based on media queries) get applied to the toolbar while it's floating
** Added animation for toolbar wrapper margins
** Added resize handler to update left and right positions on the toolbar when it's floated
* Changed from using generic "float" and "bottom" class names which are likely going to get re-used elsewhere and cause issues
Change-Id: Ic596b2b8aceb8a2d81539e197ef4d6e17326a87a
Some of the HTML structure in the suggestions might need to be changed to pull off pixel-perfect reproduction of the original design, but this gets us very close.
Change-Id: Ie574577af4815e4f0fc9f8a03e57759dd9dfff84
There is a TODO about this but these were never handled. This lack of
handling caused weird offset issues when editing paragraphs containing
inline aliens, because the text of the inline alien was returned.
Instead, return an appropriate number of characters so the offset logic
keeps working.
Removed the textContent||innerText code because it would bypass the
uneditable node logic: paragraphNode.textContent would return the text
of the entire paragraph (including any aliens), and we'd never descend
into the paragraph to reach the alien node.
Change-Id: Ia05755755dd5380cb9a0b5a0334c6721b4e0d3b7
Don't try to restore the selection after the removal part of
onContentChange, because the removal may have caused that selection to
now be out of bounds. We also don't need to set the selection there at
all, because the insertion does it anyway (where it is safe).
Change-Id: I7b340b18dd8efc77d1df78007161720c29866cb6
Make ve.dm.Surface.change accept array of transactions as a parameter (instead of just one) and use it in complex content removal (handled in Surface view).
Change-Id: I453b3606cefe140db206f5a2d2c9036bcbd639c9
The error occurred after pressing backspace in a paragraph that
contained an alienInline node (or other inline node). It happened
because ve.ce.BranchNode.clean() called this.$.empty(), which destroyed
all element data in the paragraph's children, including the
.data('node') property which associates the DOM node with the CE tree
node. Use .detach() instead.
Change-Id: I563c936a706a1d1711e6333404c6ca8e6ebf8eeb
-Using keydown on arrows allows preventDefault which stops the cursor movement in the input.
-Consolidated Keydown bindings, no longer unbinding keydown, instead checking for visible state first.
-Using case insensitive comparison for selected item.
-Changed use of ve.inArray to ve.indexOf because method name was changed.
-Moved clear break into suggestion container rather than after it.
Added margin bottom on suggestion container for category separation.
Change-Id: I2bd1db049a948db189194037dc8e38dfe884c197
Created jQuery plugin MultiSuggest which builds a categorized dropdown
under specified input box.
Revised inspector to no longer be an iframe but to contain an Iframe.
This reduces xbrowser issues with positioning and toggling inspector
container.
Added Inspector overlay element for positioning arbitrary elements
over the iFrame. This prevents growing the iframe to arbitrary lenghts.
Change-Id: I8efbbd091b0b24a19a4b73aa122d21a329cf97e4
When the document is empty, there is no last branch, and it causes an error because the code was assuming there was always going to be a last branch.
Change-Id: I371dce89db6258d30a11022c1bdb11830f59505d
* Summary label is now placeholder text
* Edit summary and options are visually connected
* Added summary length count-down label
* Removed check-mark icons from toolbar and dialog save buttons
* Made toolbar and dialog save buttons the same size
* Reduced line-height and margins of license information
* Changed from X icon for close (which might be confused with cancel) to ^ icon for collapse
Change-Id: Ib1711f49af8929be12796aecdea49467b726856e
* When you visit the page with url# (empty target) it scrolls down - which made setting the URL of the namespace tab to # really bad, plus it was useless since we already handle that click using JS
* Found that this.$toolbarWrapper wasn't pointing to the right place because of a missing .end() call at the end of a chain of jQuery madness
Change-Id: I7dc6953e39d4081f1b91a351bb830e4c18f7b988
Also:
* Made a fragment with a null range become a null fragment
* Fixed incorrect order of arguments for binding a handler to transact event
* Added getters for surface, document and range
* Fixed several instances of passing a document instead of a surface into the constructor of a new surface fragment
* Fixed closest mode in expandRange - needed to check if parent existed before checking for it's type
* Fixed uses of ve.Transaction (doesn't exist) that were supposed to be uses of ve.dm.Transaction (does exist)
Change-Id: Ide13d9d2d1637399188c98c2e8b6e0826caeecc4
When a document is created, it should take it upon itself to make sure it has a new reference to the data using slice, not place this on the caller. Callers that do not use slice will often find strange and mysterious things going on and not know why. The real reason is that multiple documents sharing a reference to the same data array leads to seriously messed up behavior.
Change-Id: Ic4e25fcd9bf3f41a805003520a8f38e2768f5dbf
domToData wraps bare content in paragraph elements, which were then
converted to <p> tags by domToData. With this fix, HTML with "missing"
<p> tags actually round-trips through the editor correctly now, rather
than having <p> tags added wherever VE believes they should exist.
* Mark generated paragraph elements with .internal.generated = 'wrapper'
** This signifies the wrapper was generated but its contents were not,
so the right thing to do when converting back to HTML is to remove
the wrapper and keep the contents. We might want to use other values
of generated in the future.
* Unwrap nodes with generated=wrapper when converting to HTML
Tests:
* Add 'generated': 'wrapper' as appropriate. Only affects 1 test
* Remove 'normalizedHtml' for this test because it is no longer needed
** Need to keep 'normalizedHtml' for now because we normalize hrefs
* Eventually the main example should test bare content, but that
requires touching a lot of stuff. The main example could use some
beefing up anyway.
Change-Id: I277ad5fe3f64e07c1bbf49007d6bbaecc90b7466
This allows us to put other internal data in there in the future. Also
passing it through the Node constructor properly now.
* ve.dm.Node
** Rename fringeWhitespace property to internal
** Add internal parameter to constructor
** Remove setFringeWhitespace()
* Increase the number of parameters passed through by ve.Factory to 3
* Pass through .internal from linmod to nodeFactory in ve.dm.Document
* ve.dm.Converter
** Rename .fringeWhitespace to .internal.whitespace and make it an array
** Store a temporary reference to .internal in domElement.veInternal
* Add internal to all node constructors except TextNode
Tests:
* Update for fringeWhitespace->internal rename
* Add third parameter to ve.Factory tests
* Add .internal to getNodeTreeSummary
Change-Id: If20c0bb78fee3efa55f72e51e7fc261283358de7
This makes a lot more sense when you start making a surface fragment from a new surface, because a null range would seem to have unpredictable behavior.
Change-Id: I85210878deca3067960fa4a14e2a760e55f67e4e
* Made vector specific styles only active in the vector skin
* Added apex specific styles
* Removed override of text size for document node
* Added stylesheet for stand-alone to specify text size for document node
Change-Id: I8a57918912499f9453a5692ff45a04a16ed34cde
To do this, we are using the replacer callback of JSON.stringify, which is supported by all of our target browsers including IE8. We are also leaning on Object.keys and Array.reduce, the latter of which required adding a new fallback implementation for some browsers which do not support it yet.
Change-Id: Ifa285ca3da4d94d962464f09414591532bbea79c
Because the Parsoid prefix format changed from /mw:Foo to /mw/Foo , the
href format for internal links has changed from "/Foo" to "Foo". So the
href is now simply the title, except that it may be preceded by one or
more "../" if the title of the page we're on contains a '/'.
So instead of stripping the leading slash from internal link hrefs and
putting it back on the way out, only strip any leading "../"s and dump
the titles directly into the hrefs on the way out.
Also update the link test case for this, and add a test case for the ../
stripping.
Change-Id: I3e0bdde20f22cda34eb45fc351de5e780419b6a2
Annotation types with more than one slash such as 'link/ExtLink/URL'
weren't being processed correctly because .split( '/', 2 ) throws away
everything after the second slash. Instead, don't pass a limit to
.split(); the code for reconstructing a slash-separated string from
multiple components was already in place.
Also add test cases for URL links and numbered links.
(Do you like the lines-of-code to lines-of-test ratio in this commit,
Trevor? ;) )
Change-Id: I7add87396447a01b1c23a4f9bfd63d2e8fd861ce
Refactor:
* ve.indexOf
Renamed from ve.inArray.
This was named after the jQuery method which in turn has a longer
story about why it is so unfortunately named. It doesn't return
a boolean, but an index. Hence the native method being called
indexOf as well.
* ve.bind
Renamed from ve.proxy.
I considered making it use Function.prototype.bind if available.
As it performs better than $.proxy (which doesn't use to the native
bind if available). However since bind needs to be bound itself in
order to use it detached, it turns out with the "call()" and
"bind()" it is slower than the $.proxy shim:
http://jsperf.com/function-bind-shim-perf
It would've been like this:
ve.bind = Function.prototype.bind ?
Function.prototype.call.bind( Function.prototype.bind ) :
$.proxy;
But instead sticking to ve.bind = $.proxy;
* ve.extendObject
Documented the parts of jQuery.extend that we use. This makes it
easier to replace in the future.
Documentation:
* Added function documentation blocks.
* Added annotations to functions that we will be able to remove
in the future in favour of the native methods.
With "@until + when/how".
In this case "ES5". Meaning, whenever we drop support for browsers
that don't support ES5. Although in the developer community ES5 is
still fairly fresh, browsers have been aware for it long enough
that thee moment we're able to drop it may be sooner than we think.
The only blocker so far is IE8. The rest of the browsers have had
it long enough that the traffic we need to support of non-IE
supports it.
Misc.:
* Removed 'node: true' from .jshintrc since Parsoid is no longer in
this repo and thus no more nodejs files.
- This unraveled two lint errors: Usage of 'module' and 'console'.
(both were considered 'safe globals' due to nodejs, but not in
browser code).
* Replaced usage (before renaming):
- $.inArray -> ve.inArray
- Function.prototype.bind -> ve.proxy
- Array.isArray -> ve.isArray
- [].indexOf -> ve.inArray
- $.fn.bind/live/delegate/unbind/die/delegate -> $.fn.on/off
Change-Id: Idcf1fa6a685b6ed3d7c99ffe17bd57a7bc586a2c
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
It was replacing spaces with s in its copy of a slice of linmod
data, but the copy was a shallow copy, so when modifying annotated
spaces it would modify the actual data. Fixed by detecting this case and
cloning the character's array before modifying it.
Change-Id: Ic96ed34605a302af18f274a0faa6d0f650f5b771
Also added some checks in content branch conversion to make sure that converting from and to the same thing results in a no-op
Change-Id: Ie47520d666e45a77d12c7ebb9457aef7ab6b8097
* Per Krinkle's comment, be tolerant of missing .htmlAttributes
* Drop .htmlAttributes if no attributes, fixes some tests
Change-Id: I65589a8b489e19a7c8a41ba2f4a57e68fc52684c
* Restricting "camelcase":
No changes, we were passing all of these already
* Explicitly unrestricting "forin" and "plusplus"
These are off by default in node-jshint, but some distro of jshint
and editors that use their own wrapper around jshint instead of
node-jshint (Eclipse?) may have different defaults. Therefor
setting them to false explicitly. This also serves as a reminder
for the future so we'll always know we don't pass that, in case
we would want to change that.
* Fix order ("quotemark" before "regexp")
* Restricting "unused"
We're not passing all of this, which is why I've set it to false
for now. But I did put it in .jshintrc as placeholder.
I've fixed most of them, there's some left where there is no clean
solution.
* While at it fix a few issues:
- Unused variables ($target, $window)
- Bad practices (using jQuery context for find instead of creation)
- Redundant /*global */ comments
- Parameters that are not used and don't have documentation either
- Lines longer than 100 chars @ 4 spaces/tab
* Note:
- ve.ce.Surface.prototype.onChange takes two arguments but never
uses the former. And even the second one can be null/undefined.
Aside from that, the .change() function emits
another event for the transaction already. Looks like this
should be refactored a bit, two more separated events probably
or one that is actually used better.
- Also cleaned up a lot of comments, some of which were missing,
others were incorrect
- Reworked the contentChange event so we are no longer using the
word new as an object key; expanded a complex object into multiple
arguments being passed through the event to make it easier to work
with and document
Change-Id: I8490815a508c6c379d5f9a743bb4aefd14576aa6
Right now this means things like headings and list items are rendered
nicer (without the whitespace), but also get their whitespace normalized
when saving back. I'll submit code tomorrow that preserves this
whitespace.
Submitting this now because it's needed to make <br>s look reasonable
Change-Id: I4b5e5ad8ee1bbe2f1eaf0fb860dd59f6e401dc3d
The new annotation API will do this too; this is a temporary hack to fix
the bugs caused by stripping attributes.
This code doesn't actually render the attributes, but the new annotation
API will.
Change-Id: Ic0ddf822fe02f101f2e825080c6bcc2a03115974
Stack traces, line numbers, etc. All the approaches I've seen are bad hacks. This is the best way to go.
Change-Id: Ib12e9d2ecfe610bcc89d046005e35cc13efa3d99
Throwing strings is bad because it doesn't include a lot of important
information that an error object does, such as a stack trace or where
the error was actually thrown from.
ve.Error inherits directly from Error. In the future we may create
more specific subclasses and/or do custom stuff.
Some interesting reading on the subject:
* http://www.devthought.com/2011/12/22/a-string-is-not-an-error/
Change-Id: Ib7c568a1dcb98abac44c6c146e84dde5315b2826
* Use 'href' of #ca-edit instead of constructing it manually.
MediaWiki's output of #ca-edit already takes care of all needed
queries, including "oldid" (bug 38125).
* Misc clean up:
- Use .get() instead of accessing the array directly.
* Clean up setupSkinTabs and add more inline documentation.
Change-Id: I7d702a3eb1f9ce23a5e3c9e846b00da5cead386e
* There were only 3 files with single quotes, fixed them all.
* Added option to .jshintrc (be sure to use the latest version of
node-jshint since this is a fairly new addition to the library).
Change-Id: I8bf8895ce56bf86e3bed244279a9d32269e44763
This just cleans up a few places where single quotes should have been used instead of double quotes.
Change-Id: I6c53652e71ab96842ed5bb41fb1e0b8c923eb25d
When closing annotation nodes, we weren't popping them off
annotationStack. Not sure where this came from, but the code was
definitely bad and this fixes it.
Change-Id: I6d805e9aca3778666212135f76ff34c6baacbbc8
* Default value of wgVisualEditorParsoidURL is broken.
Slash is needed, else Api will request to
http://hostnamePageName
Roan says double slashes are okay, and look cleaner than string
search checks etc.
* Use .clone() for mw.Uri instead of converting to string
and letting mw.Uri parse it, again. Clone creates a basic
instance and copies over properties internally (deep copy,
no references).
* No need for hasOwnProperty (and its potential issues)
* Code clean up
- Whitespace consistency
- Variable hosting
- Remove redundant `return false;` statements in event handlers
e.preventDefault() is a jQuery.Event method that takes care
of cross-browser issues.
- Same for e.keyCode||e.which thing, this is already normalized
by jQuery.Event
- Add missing parameter to setTimeout
- Consistent order in success/error handlers in $.ajax options
Change-Id: I5bc24e0cbdf01b3704d4ccb0b45b3052e3b58694
Also:
* Removed a lot of dead code in Surface that was used in the now dead and gone sandbox.
* Changed from throwing an exception when calling getBalancedData on a range that produces no results from selectNodes to just returning []
Change-Id: Icf27094724eae5b90eec21308f9e26afe877e3ee
When editor surface loses focus, now checking to see if an inspector
is set or a menu is open prior to closing the context.
This ruling ensures more rational context icon / child menu behavior.
Change-Id: Ic4b74bb51e811e264a2109a3c1c5a8ae503a8c49
* Classicifation (JS)
Use addClass instead of attr( 'class' ) whenever possible.
addClass will manipulate the properties directly instead of
(re-)setting an attribute which (most) browsers then sync
with the properties.
Difference between:
elem.className
and
elem.setAttribute( 'class', .. );
Just like .checked, .value, .disabled and other interactive
properties, the HTML attributes should only be used for initial
values from the html document. When in javascript, only set
properties. Attributes are either ignored or slow.
* Styling (JS)
Use .css() instead of attr( 'style' ).
Again, setting properties instead of attributes is much faster,
easier and safer. And this way it takes care of cross-browser
issues where applicable, and less prone to error due to dealing
with key-value pairs instead of css strings.
Difference between:
elem.style.foo = 'bar';
and
elem.setAttribute( 'style', 'foo: bar;' );
* Finding (JS)
Use .find( 'foo bar' ) instead of .find( 'foo' ).find( 'bar' ).
It is CSS!
* Vendor prefixes (CSS)
It is important to always list newer (standards-compliant) versions
*after* the older/prefixed variants.
See also http://css-tricks.com/ordering-css3-properties/
So the following three:
-webkit-gradient (Chrome, Safari 4)
-webkit-linear-gradient (Chrome 10, Safari 5+)
linear-gradient (CSS3 standard)
... must be in that order.
Notes:
- "-moz-opacity" is from before Mozilla 1.7 (Firefox < 0.8)
Has not been renamed to "opacity" since Firefox 0.9.
- Removed redundant "-moz-opacity"
- Added "filter: alpha(opacity=**);" where missing
- Fixed order of css3 properties (old to new)
- Add standardized css3 versions where missing
(some 'border-radius' groups didn't have the non-prefixed version)
- Spacing
- @embed
- Shorten hex colors where possible (#dddddd -> #ddd)
$ ack '#([0-9a-f])\1{5}' --css
$ ack '#([0-9a-f])\1{2};' --css
Change-Id: I386fedb9058c2567fd0af5f55291e9859a53329d
* Also update test/index.html with latest minimalistic format
* Update test suite hardcoded paths to match the definition in
VisualEditor.php for ResourceLoader
* Issues:
- 'jquery/jquery.json.js' should not be loaded directly,
using a dependency instead.
- Load scripts from the <head> in test/index.html so that
code that depends on document being ready is catches instead of
silently being ignored.
Change-Id: I5ad7390137f4d17c153a1bf69f19c4869c08e323
-Bug 38042
Save dialog description field doesn't respond to 'Enter' or 'Return' keys
-Bug 38621
Pressing 'Esc' in Save-dialog should exit saving, return to editor
Change-Id: I9c43c6c9f2f2b538becc4fbbce1eda6e918d4879
'''Kranitor commits''' are commits by Krinkle with his janitor hat on.
Must never contain functional changes mixed with miscellaneous changes.
.gitignore:
* Add .DS_Store to the ignore list so that browsing the directories
on Mac OS X, will not add these files to the list of untracked
files.
* Fix missing newline at end of file
.jshintrc
* raises -> throws
* +module (QUnit.module)
* remove 'Node' (as of node-jshint 1.7.2 this is now part of
'browser:true', as it should be)
Authors:
* Adding myself
MWExtension/VisualEditor.php
* Fix default value of wgVisualEditorParsoidURL to not
point to the experimental instance in WMF Labs.
Issues:
* ve.ce.TextNode:
- Fix TODO: Don't perform a useless clone of an already-jQuerified object.
- Use .html() to set html content instead of encapsulating between
two strings. This is slightly faster but more importantly safer,
and prevents situations where the resulting jQuery collection
actually contains 2 elements instead of 1, thus messing up
what .contents() is iterating over.
* ve.ce.Document.test.js
- Fix: ReferenceError: assert is not defined
* ve.dm.Document.test.js
- Fix: ReferenceError: assert is not defined
* ve.dm.Transaction.test.js
- Fix: ReferenceError: assert is not defined
* ve.dm.TransactionProcessor.test.js
- Fix: ReferenceError: assert is not defined
* ext.visualEditor.viewPageTarget
- Missing dependency on 'mediawiki.Title'
Code conventions / Misc cleanup
* Various JSHint warnings.
* Whitespace
* jQuery(): Use '<tag>' for element creation,
use '<valid><xml/></valid>' for parsing
* Use the default operator instead of ternary when the condition and
first value are the same.
x = foo ? foo : bar; -> x = foo || bar;
Because contrary to some programming language (PHP...), in JS the
default operator does not enforce a boolean result but returns the
original value, hence it being called the 'default' operator, as
opposed to the 'or' operator.
* No need to call addClass() twice, it takes a space-separated list
(jQuery splits by space and adds if needed)
* Use .on( event[, selector], fn ) instead of the deprecated
routers to it such as .bind(), .delegate() and .live().
All these three are now built-in and fully compatible with .on()
* Add 'XXX:' comments for suspicious code that I don't want to change
as part of a clean up commit.
* Remove unused variables (several var x = this; where x was not
used anywhere, possibly from boilerplate copy/paste)
* Follows-up Trevor's commit that converts test suites to the new
QUnit format. Also removed the globals since we no longer use those
any more.
Change-Id: I7e37c9bff812e371c7f65a6fd85d9e2af3e0a22f
This should make it much simpler to keep MediaWiki specifics out of VisualEditor, which will in turn make it easier to integrate VisualEditor into another platform.
Change-Id: I073e9737b37c28af889f2457d10b082cefd0d63b
Convert underscores in the href attribute to spaces in the linear model,
and back to underscores when going back to HTML. This ensures the link
targets displayed to and edited by the user look nice
Change-Id: I4855fce28ad8b724284c53881abc7b99b59b9079
Clearing context icon when editor loses focus.
-Reproduce problem by selecting text, then click outside of
the editor. Selection is lost, and context icon is stuck.
Change-Id: I4b321f16cea73ec0e51540c0e71f265ab47514e9
This means we don't have to rely on data-rt.sHref. It also means that
we'll now be showing the canonical link target in the link inspector
rather than the link target as entered by the user, but that's fine.
Also change test to have href differ from sHref to show that we use
href.
Change-Id: Idabdbf2579663ef1efb47d6a73f39743c9f64f3b
This is ugly but makes things work again. I intend to clean this up once
we have a better attribute API
* Recognize mw:WikiLink, mw:SimpleWikiLink, mw:ExtLink,
mw:NumberedExtLink and mw:UrlLink
* Support is incomplete because we can't get to the annotation text with
the current API
* Preserve all unhandled attributes rather than special-casing data-mw
* Update remaining code using data-mw (sHref and stx extraction) to
account for the data-mw -> data-rt rename
* Update tests accordingly
Change-Id: Ia13d3008a6d4cdc8828f9acda5aa797566bc597f
- Attaching save dialog to toolbar wrapper vs toolbar itself.
- Attaching surface specific toolbar wrapper vs all toolbar wrappers
in the case of multiple editors on the page.
Change-Id: Ic81f5a680f5593c71c27b7d47fe246487eebd4a3
(or this shouldn't be allowed)
-Revised method for for returning all link annotations in a
selection. Now properly clearning all selected links.
-Trimming whitespace from selection
-Modifying selection if it doesn't contain annotated range
-Disabled link creation only if target is blank. This allows
Existing link text to be modified while having the same target.
Change-Id: I7255dcf1c88fa1cd6e7edbc3baa82cd4c72a95d1
-Hide / show inspector with visibility vs display property
for iframe cross browser compatibility.
Change-Id: Ibdd0250872c42d74d6ff7d22abdf9d838962acc1
This was caused by a bug in fixupInsertion that caused it to believe
that inserting something like "a</p><p>b</p><p>c" into the middle of an
empty paragraph was invalid.
This commit fixes the fixupInsertion bug, which fixes the
select-all-cut-paste behavior in Chrome. It's still broken in Firefox
because of selection-related issues, but I'll split that out into a
different bug report.
Change-Id: I767f5d37ec7e511778ae9ca8283ec4b26c728298
In RTL interface the drop-down arrow overlaps with the text.
The arrow was positioned explicitly in relation to the left margin, and this
can't work in a flipped RTL environment. I changed the position to "right"
and modified the arrow image a bit.
Some visual tweaks to the arrow may still be needed. Another option can be
to convert the image to SVG or to use a character like ▼.
Change-Id: Ib09a2a20b150de6e8a9531fc0db7dfffe4e95525
- Added limits to toolbar float, Toolbar will not go past the last node in editor.
- Added bottom mode to allow toolbar to stick above the last node until the scroll position
is above the last node.
- Actually checking toolbar config now and setting float when flag is set.
- Gave float method for top toolbar a better name.
Change-Id: Ic39c5402fa7a05e13c5e81722d8729d93776d7e9
But still put slugs before them. Done by overriding canHaveSlugAfter()
in ve.ce.ListNode.
Eventually this should be configurable and MediaWiki-specific
Change-Id: I5ad15ca4085a2d730add4954acbea358819b3986
These determine whether a node can have a slug before and after,
respectively. The default implementation in ve.ce.Node is to use the
same rules for both, but individual node types can override this.
I'll need this to suppress slugs after nested lists but not before them.
Change-Id: Id88c0fc98aca7c7f52ce990ed9b8c42181ef6d18
For pressing Enter in an empty list item at the end of a top-level list,
this has the same result as the previous code, but if you're in a nested
list it has the effect of jumping down a level. A previous incarnation
of this change just made Enter insert more list items ad infinitum if
you were in a nested list, but I think this is better.
This fixes a bug where pressing at the end of a nested list inserted a
paragraph in an invalid location
Change-Id: I9c7dbaf29a98f84926ed3a05e71c6294926dfce2
Fix the commented-out code: it caused unindent to be triggered by just
pressing Shift. ASCII 16 is "data link escape", no idea where that came
from, so I removed it and used e.shiftKey instead.
Also check whether indent/outdent is even possible before doing it.
Currently this is done in a very hacky way (by checking the state of the
indent button), ideally we'd refactor things such that toolbar tools can
listen for keydowns and intercept them, that would make the code much
cleaner and we wouldn't have this problem.
Change-Id: I99885ee4b8a79cd24c4958c188addfc2b0453b03
After indenting or outdenting a list item in a numbered list, the
numbering wasn't updated. So if you had:
1. One
2. Two
3. Three
and you indented "Two", you'd get:
1. One
1. Two
3. Three
Adding or removing items in the list using the keyboard, or even
inspecting the list in Firebug (!), would trigger a renumbering and fix
the list to display "2. Three". But then the same issue would occur in
in reverse when outdenting "Two" (either using undo or using the
outdent button):
1. One
2. Two
2. Three
The workaround is to force a reflow by requesting the height (thank you
Timo). Implemented this in an override of onSplice() in ve.ce.ListNode, so
the list is detached and reattached every time children are spliced into
or out of it.
I haven't managed to come up with a minimal test case for this, not even
by putting a list in a contentEditable div and doing the same DOM
operations that ve.ce does from a setTimeout callback.
Change-Id: I93b2a309034c411a7b4e4b6c6bd4ef9d473999eb
This works pretty well, the only problems I found are:
* when selecting multiple list items, only the first is in/outdented
* there's no special handling for child lists, so the behavior for
in/outdenting list items that have a child list can look weird, but
it's consistent
Also needs more documentation
Change-Id: I6f4f3725e57a590196d7d638a77b87ea85586dc8
* When ascending back up the stack, check for a start between two closings
* Also check for an end between two openings
* This introduces code duplication but selectNodes() is full of that
already. I'll have to do a duplication cleanup soon
* Add test case for </li><li>
* Update existing test case that covered a </li>
Change-Id: Ifc80585ce0e0d6988bc54228602c69f0d519200a
For nested lists, this function would return multiple groups where one
was wholly contained in the other, use offsets to prevent that from
happening.
Change-Id: Ib03bb1c81712d805cc263c2975cc3942de63d2ed
to be added. Create inspector elements in the propper document
scope. Restore inspector css classnames to camel case for proof
that inspectors are being created in the correct document scope.
Previously, inspector elements created in the wrong document scope
would have css rules applied only if class names were lowercase.
Issue only surfaced in Webkit browsers. Though, this implementation
is more future proof and will help prevent future inspector bugs.
Patch 3) Fixed global variable definition and mistake with
inspectorDoc
Change-Id: I36c0d078aea10d919689768878004a19f7f89b55
-Selection of part of a link now modifies selection to entire link
range on inspection.
-Retaining selection direction on new range
Only partial fix to bug as previous link annotation is not
yet properly cleared.
Bug 33053 - VisualEditor: Link creation should not include trailing
spaces, and should provide a suggestion based on selected text
-Created method to return a new range without outer spaces.
-Retaining selection direction on new range.
-Enhancement needed for link suggestion.
Bug 33108 - VisualEditor: Highlighted trailing whitespace should
not have styles applied
-Modified trim method to retain selection, added call to trim
range on annotate method.
Change-Id: I92f264e19350c62b7c2ac3cd9e78af0071afef5c
This license change is aimed at maximizing the reusability of this code
in other projects. VisualEditor is more than just an awesome editor for
MediaWiki, it's the new editor for the entire internet.
Added license and author files, plus mentions of the license to all
VisualEditor PHP, JavaScript and CSS files. Parser files have not been
modified but are effectively re-licensed since there's no overriding
license information. 3rd party libraries are not changed, but are all
already MIT licensed.
Change-Id: I895b256325db7c8689756edab34523de4418b0f2
* "onevar" warning sometimes solved by just merging var statements
other times solved by making it a function declaration instead
of a function expression.
* Also fixed several '_this' variable names in ve.es.Surface to
more descriptive names, and enabled warnings for dangling _
in identifiers.
Change-Id: I7d411881e3e06cf9a7fe56d689c29375881a81de
This fixes a bug Trevor reported where selecting from a list item across
a heading and into a paragraph, pressing backspace, then clicking undo
caused an exception.
Change-Id: Id2851271529e10548f6979a030a198054aa1c48f
ve.ce.TextNode listed textStyle annotations that didn't actually exist,
and failed to recognize some that did exist (such as span; bug 37808).
Added all annotations to both places. <span> tags are now tolerated by
the editor in that it doesn't crash anymore, but they're displayed (and
saved!) without any attributes, so <span style="color:yellow;">y</span>
doesn't show a yellow 'y' in the editor and is saved back as
<span>y</span> .
Change-Id: Iaae11ad5044150fa904010983ff83579cb37733d
Fixed by adding the specialMessages module which is only loaded once the
editor loads. Then after it's loaded we use the summary message from
there to update the (possibly broken) summary message in the save
dialog.
Change-Id: I67f5c59501cdf7c66c925cef8d4dd42b0f2cfde3
* changes:
Got rid of iteration to get the surface
Removed attach and detach methods from ve.ce.Node
Track adjustments in DocumentSynchronizer and apply them to oldRange
This is needed because oldRange is relative to the state of the model before any changes were made, but when we call selectNodes() it's gonna operate on a partially updated model tree.
This is a genuine bug in DocumentSynchronizer proper, which means I owe the entire team lunch
Change-Id: Ia6510de19df02e961c7f25fb8e7833abceb8d25b
* Adjust both start and end for preceding operations
* Adjust end for the current operation as well
Change-Id: I2f96d609bddf3788aa5700ad1f0b46208f3517d7
text for a link is the selected text.
patchset 2 - add case for if data offset is an object, be sure it
is a string prior to adding it. truncate to 255 chars.
patchset 3 - actually add the patched file
Change-Id: Ibddf942c2a0ba3412d93cf9730f74eb858025fad
Also fixed unlisting to not break when unlisting a range that includes things that are not list nodes
Change-Id: Ib9d4ea851c3ed9bf72a93aa87e470ce40c308453
contained by a list node the button is off. Button is now only toggled on
if all nodes in selection have a parent list node.
Patchset 2 - cleanup whitespace
Change-Id: Ia9adc39c0d5c75e2e96580f0e172f5b602540ac3
to update save dialog checkbox with correct watched state.
Call mw.page.watch.updateWatchLink onSave to refresh icon
with watched state.
Patchset 2- updated event name
Change-Id: I23ef1aad9c8ace13df1b9a6bf0bfeddb9d8bcb37
Now setting up multiple toolbars per config
Tools & Modes are now configurable per toolbar per instance
Base elements are created on demand and no longer id specific
Note: There are some bugs with multiple instances.
Change-Id: Id0bbbca2d1b76fd2db3f3b0f9abd90194930b610
Renamed Selection method to more suitable name.
Misc cleanup
Patchset 2, whitespace cleanup
Patchset 3: Change values used with selection direction to -1 or 1
1 for left to right (normal)
-1 for right to left (opposite)
Change-Id: If9ecc721ace1c7550903170f92395947f1ccc22c
Ground-up rewrite of the data model. Putting this in the ve2 directory for now so we still have the old code floating around.
Main changes so far in this rewrite:
* Renamed hasChildren() to canHaveChildren()
* Added canHaveGrandchildren()
* Added a new node type TwigNode that can have children but not grandchildren (so all of its children must be LeafNodes)
* Implemented push/pop/shift/unshift as wrappers around splice()
* Renamed getElementType() to getType(). Nodes now take a string as a type, and the element stuff is gone and won't be back
* Removed clearRoot(), replaced it with setRoot( this ) where needed
Change-Id: I23f3bb1b4a2473575e5446e87fdf17af107bacf6
This has some TODOs still but I want to land it now anyway, and fix the
TODOs later.
* Add this.offsetMap which maps each linear model offset to a model tree node
* Refactor createNodesFromData()
** Rename it to buildSubtreeFromData()
** Have it build an offset map as well as a node subtree
** Have it set the root on the fake root node so that when the subtree
is attached to the main tree later, we don't get a rippling root
update all the way down
** Normalize the way the loop processes content, that way adding offsets
for content is easier
* Add rebuildNodes() which uses buildSubtreeFromData() to rebuild stuff
* Use rebuildNodes() in DocumentSynchronizer
* Use pushRebuild() in TransactionProcessor
* Optimize setRoot() for the case where the root is already set correctly
Change-Id: I8b827d0823c969e671615ddd06e5f1bd70e9d54c
Effectively stopping & starting polling prior to conversion
Getting Selection from model
Reselecting after conversion (TODO: modify selection to entire block ?)
Change-Id: I9ba331b5393bf568cc8d137646b43244ae2640a8
This makes it possible to get identical rendering in the editor, but may make other things more complex. The Wikitext serializer is no longer compatible for rendering lists so it's been stubbed out. Also the way the toolbar works with lists is broken, so that's been disabled. The HTML serializer has been fixed to work correctly and no-longer-used styles have been removed.
Change-Id: If156f55068b1f6d229b3fa789164f28b2e3dfc76
Also:
* Simplified ve.ce.Surface.getLeafNode, which may be better to just be removed and be used inline in the few places it's being used.
* Removed method wrapper for static function ve.ce.Surface.getLeafNode
Change-Id: I1d4cf0bb7ecc8f07f030753e40a13ebef7d02daa
* This high level surface object is responsible for creating & managing editor instances
* Revised Sandbox demo to invoke in this way.
Change-Id: I4043779af9a2ab964deaf26079a992e82ebeef27
To handle replace operations that are not themselves consistent (these
are common, for instance when replacing an opening element in one place,
then replacing the closing element somewhere else), we process
subsequent replace operations inside the first one until things are
balanced again, then issue a single rebuild for the whole thing.
Change-Id: Ide4613f046fabfeeef383138c39e350b1b710033
Have created builders for insertion, removal, and single element replacement.
In adding Document.getMetadata which is nearly identical to Document.getData,
the two functions have been refactored to use a common static method
getDataSlice, with this.data/this.metadata as an argument.
Document.spliceMetadata has been added. It is essentially spliceData with
the data/metadata synchronisation issue.
Metadata cursor position is now tracked in the TransactionProcessor. Cursor
advancement has been moved to a function so the metadata cursor can be reset
every time the data cursor is moved.
There were unhit bugs in the TransactionProcessor run test section, where
the data being loaded into the test documents wasn't always being deep-copied,
and the assert was looking at getData instead of getFulldata (which wouldn't
be able to test metadata changes).
Change-Id: Ieb20ab3e7827bc7ff04148f147da6728eb1eb666
* New! Button and InputLabel widgets
* Using new buttons in the demo
* Moved styles around to generalize input styles
Change-Id: Ic42e133f8fe0fffcb61374c09dd5668db82a4799
TODO: Use these buttons other places! (like ve.init)
The specific use case is when user clicks on the left side of the inline alien node which
is at the beginning of the line or on the right side of the inline alien node at the end of
the line. This fix does not cover Monobook.
Change-Id: Ib24b03e30e753850698ed6b10be49b4f2642c92b
Refactored the (previously unused) eg-iframe file to be a
template with 2 placeholders for script and styles.
The previous version was just the basic version to execute
javascript code, but that's not good enough since we need a
whole bunch of classes to be loaded.
A bash file processes the template into proper html, with the
help of the makeStaticLoader maintenance script we already had.
Updated demo.css, cleaned up redundant properties restyled
slightly to be more like the Vector skin and less "raw".
Fixed default $IP path in makeStaticLoader.php to work with simple mediawiki core installs having the extension in the
regular extensions directory, and prefixed __DIR__ so it
doesn't rely on the directory you call it from.
Change-Id: Ic789121dfeca08d9db69564d2ad2e52b3fa45de9
This gets rid of the meta-specific hack in ve.dm.Document
Later on, I want to use this to get rid of meta-specific hacks in the
converter too, by pushing some of that logic into the ModelFactory.
Change-Id: I1dbee1654fa32d9c7cd521ec325b2553cde219d1
Fixes (Bug 44086)
Changes:
ve.ui.LinkInspector.js
- Annotate fragment for affected range.
- Fragment returned by insertContent was a zero length range, therefore
no content was being annotated. It is questionable whether insertContent
should return the affected range or not.
- Also changes behavior of editing existing link annotations so that the cursor is after the annotation rather than covering it when the inspector is closed
Change-Id: Ic53b9844f84781cad05ac1f63964c9aaf7de68c3