We got lucky - the fact that our alien styling choice required phantom overlays had the nice side-effect of preventing the ability to focus the aliens. Therefore, as soon as we started ignoring IE to deliver nice alien handling for standards-compliant browsers, we inadvertently solved(?) the IE alien problem. I've touched up the styling to look nice in IE 9 (solid green phantoms) and IE 10 (stripes). Shield GIF switched to PNG because IE 10 renders the transparent GIF as solid red. Yeah, red.
Change-Id: I3bc69acba9ed883a823cdf722117b90966bc332b
This solves 2 issues:
1. Paste scrolls to the top of the editable box because we temporarily moved the focus to the paste container, and then moved it back. We solve this by saving/restoring the scroll position.
2. Scroll position adjusts vertically when pasting (using key repeat) because we handle pastes with a setTimeout and multiple paste jobs will pile up before they can be finished. We solve this by disallowing paste until we are done handling the previous one. In the case of key repeat this only is observable as slowing the repeat rate.
Thank you Christian for helping me solve this the old fashioned way - by sacrificing features you don't really need!
Change-Id: I75bcf9843b57cdff0db9b6dea62d66d4d76ac011
ve.dm.Document
* 2 of the 3 paths of getSlice still returned arrays instead of ve.dm.DocumentSlice objects
ve.ce.Surface
* Translate the range using the insertion transaction and truncate it, so the cursor ends up just after the pasted content
Change-Id: If7bae5e254ec84a847c1d3527f74d9c09c2d82b4
ve.ce.Surface
* Switched to using getSlice instead of getData in copy and paste handlers
* Added try/catch which attempts to build a transaction with the unbalanced data first, but falls back on the balanced data otherwise
ve.dm.*Node
* Added default style attributes (now used by ve.dm.NodeFactory)
ve.dm.Document
* Fixed bugs in fixupInsertions where parentType was being set with an object rather than a string
* Made use of getDataElement
* Added adoption capability so that inserting a</h1><p>b into <p>c[cursor]d</p> results in <p>ca</p><p>bd</p> rather than throwing an exception
* Renamed getBalancedData to getSlice, now retuning a ve.dm.DocumentSlice object
ve.dm.DocumentSlice
* Introduced new container for balanced data and a range of the original context - useful for copy/paste
ve.dm.NodeFactory
* Added getDataElement method, which uses default attributes to create a boilerplate version of a data element
ve.dm.Document.test
* Updated getBalancedData test to be a getSlice test
demos/ve/index, VisualEditor, test/index
* Added references to ve.dm.DocumentSlice
Change-Id: Id9269a29e51ca213508de8f155d3feec5e5b0774
Since model.change now starts the surfaceObserver, a problem manifested where the surfaceObserver was observing the $('#paste') element (used for capturing and sanitizing pasted content from external sources). Simply switching the order of the transaction and the documentNode focus fixed the problem.
Change-Id: I1b542b546d7f3d97e2e954ca4b51ca74232b2877
Get rid of ve.ce.Surface.locked (and isLocked, lock, unlock) and instead introduce ve.ce.Surface.renderingEnabled (and isRenderingEnabled, enableRendering, disableRendering) which names are way less confusing and more specific. Also add use of isRenderingEnabled to ve.ce.ContentBranchNode.
Change-Id: I72e9e8f8dfbf43784d7e616369acc3e9649c715a
Initializing range var in SurfaceObserver to use this.range instead of null to avoid passing wrong information to onContentChange.
Change-Id: I1d4e3fa2393166dad887077529351a479401bf4b
ContentBranchNode shouldn't rerender on update, only on childUpdate.
When deleting across an inline node, update was emitted after the splice
had occurred in the DM but before the spice event was emitted that
caused the splice to happen in CE, leading to detached nodes and
associated sadness. See the bug for more details.
Change-Id: I2d44231b6e27efdb3f12967556cff174d9364d25
ve.ce.Surface
* Used getModel() as per TODO
* Simplified code by pre-calculating 2 statements that were being used 4 times each
* Re-structured logic so that simple insertion and deletion are only possible if next and previous have a range, triggering complex change otherwise
* Added some documentation
ve.ce.SurfaceObserver
* Added checks for whether rangy found a branch node within the document or not before accessing it's node via .data() and made it so we are only performing DOM > document range conversion if we did
* Removed some commented out code
Change-Id: Iaaf30a5b201710ab4235e775f18808a8d512f1f9
This will prevent inline alien phantoms from appearing while dragging. This was a usability enhancement identified by Inez/Christian.
Change-Id: Idf046db72e25875e899f5926ab7d50d2f514586b
This prevents memory waste when switching between read and visual editor tabs, which happens entirely on the client.
Change-Id: I31b50accac38d72a9367b9035504552dc0150104
When the content rendering stuff was moved to ve.ce.ContentBranchNode the onUpdate methods being used to update the DOM wrapper in ve.ce.HeadingNode was overlooked, so heading were not rendered on update anymore.
Change-Id: I994b8c43123c3cd02b9a550d5d7eac7d5052418e
ve.ce.Surface
* Added ve.ce.Surface.adjustCursor, which replaces repetitive and buggy code that was handling left and right arrow key presses
* New method only affects the selection target, so it won't collapse the selection on you - this was what caused bug 42401
* Made hasSlugAtOffset() actually return a boolean
ve.dm.Document
* Fixed turn-around issue in ve.dm.Document.getRelativeOffset - if the offset is already valid and we can't move in the direction we want, we should just leave it be, not turn around
* Since this method was being used by ve.ce.Surface to correct the cursor position on arrow key presses, it was causing the strange cursor jumping when you pressed an arrow key while at the edge of a document
ve.dm.SurfaceFragment
* Fixed typo where getAnnotationRangeFromSelection was preserving selection direction, but checking the wrong properties
ve.dm.Document.test
* Added tests that verify turn-around issue is fixed
Change-Id: Iba55cfc3d531e7d1333b78c94912ff22179aace8
ve.ce.Surface.handleDelete did not support inline elements. This patch resolves this by detecting them and using programatic delete instead of native browser delete.
Change-Id: I73215df88519450965be35d9e04cf4e621d1e90d
Moved annotation rendering from ce.Textnode into the new
ce.ContentBranchNode class. This allows us to render annotations that
span across multiple nodes.
* Add ce.ContentBranchNode, inheriting ce.BranchNode
* Make ce.{Paragraph,Heading,Preformatted}Node inherit ce.ContentBranchNode
* Made ce.ContentBranchNode render its child nodes with anntations,
using .getAnnotatedHtml() on the child nodes
* Put a default implementation for .getAnnotatedHtml() in ce.LeafNode
* Override this in ce.TextNode to do escaping and whitespace handling
* Removed rendering code from ce.TextNode (this.$ is now unused there)
* Removed ce.TextNode.onUpdate() and ce.BranchNode.clean(), now unneeded
* Have ce.BranchNode propagate update events from children, so
ce.ContentBranchNode can rerender when its children change
* Update tests, add test case for escaping of &<>'"
Change-Id: I4600e984b287c6ff9267f4281d2f09bab9e1ad95
* Added whitelist argument to setDomAttributes which allows filtering of attributes being set
* Added prefix argument to ve.dm.Node.getAttributes to allow extracting a subset of attributes by name prefix
* Added a whitelist to ve.ce.Node which was extracted from MediaWiki's Sanitizer class
* Replaced attribute copying code with a call to setDomAttributes using the whitelist argument, passing in attributes from a call to ve.dm.Node.getAttributes using the prefix argument
Also…
* Removed comment in constructor of ve.ce.Node, documentation for properties is usually in the getters/setters, and already was in this case
* Renamed ve.setDOMAttributes to ve.setDomAttributes
* Renamed ve.getDOMAttributes to ve.getDomAttributes
* Renamed ve.getDOMText to ve.getDomText
* Renamed ve.getDOMHash to ve.getDomHash
* Updated all callers of renamed methods
Change-Id: Id556172d5d18ea431044b9d402400e1f0e67a293
* Adjust offsets to correct positions before showing selection with them
* Throw an error inside of getNodeAndOffset if we can't find a match rather than mysteriously not retuning anything
Change-Id: Ia7347527e6466262e819f456404b32926fd95e34
ve.dm.SurfaceFragment
* Removed flawed implementation of word mode for expandRange method and made use of new getNearestWordBoundary method in the document model
ve.dm.Surface
* Got rid of useInsertionAnnotations, which allowed disabling and enabling of insertion annotations - this isn't needed anymore because it was just a dirty hack around the improper starting and stopping of surface observer that's now solved more elegantly by emitting lock and unlock before committing or rolling back transactions
* Get annotations from the first character of the selection if the selection is not collapsed
* Only emit annotationChange events if it really changed
ve.dm.Document
* Added getNearestWordBoundary method which performs the work behind the surface fragment expandRange word method
ve.ce.SurfaceObserver
* Allow using an initial selection to avoid the observer thinking the selection has changed just because it started out with null
* Only emit selectionChange event if there was a meaningful change
ve.ce.Surface
* (bug 42279) Only annotate characters if insertion annotations are not empty
* Remove manual locking and unlocking, this is now done inside the change method of surface model
* Provide an initial selection to surface observer when we clear it
* Remove enabling and disabling of insertionAnnotations, this isn't needed anymore
* Stop/start observer on key presses that execute actions as well as those that have no special handling
ve.ce.Document
* Make getNodeFromOffsetand getSlugAtOffset return null when given -1 as an offset
Change-Id: Ibf6b26de299e54ae8688a2653bf5d5538927f8c3
Check for all node classes in getOffsetFromTextNode(), not just
branches and aliens (an entity is neither)
Render entities with contenteditable=false. Without this, selection was
still broken, because:
Foo|€Bar was really <p>Foo<span>|€</span>Bar</p> which maps correctly.
Foo€|Bar was really <p>Foo<span>€|</span>Bar</p> which maps to the same,
which is incorrect.
With cE=false, the cursor can't be inside the span, so we get:
Foo|€Bar is really <p>Foo|<span>€</span>Bar</p> which maps correctly.
Foo€|Bar is really <p>Foo<span>€</span>|Bar</p> which maps correctly.
Change-Id: Iaf603346590a9ad553c152565eb203136be7a399
<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
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
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
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