| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131 |
- /**
- * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved.
- * For licensing, see LICENSE.md.
- */
- 'use strict';
- import diff from '../../utils-diff.js';
- import Observer from './observer.js';
- import ViewElement from '../element.js';
- import ViewText from '../text.js';
- import objectUtils from '../../lib/lodash/object.js';
- import EmitterMixin from '../../emittermixin.js';
- export default class MutationObserver extends Observer {
- constructor() {
- super();
- this.config = {
- childList: true,
- characterData: true,
- characterDataOldValue: true,
- subtree: true
- };
- }
- /**
- * @method init
- * @param {treeView.TreeView}
- */
- init( treeView ) {
- this.treeView = treeView;
- this.domRoot = treeView.domRoot;
- this._mutationObserver = new window.MutationObserver( this._onMutations.bind( this ) );
- }
- /**
- * @method attach
- */
- attach() {
- this._mutationObserver.observe( this.domRoot, this.config );
- }
- /**
- * @method detach
- */
- detach() {
- this._mutationObserver.disconnect();
- }
- _onMutations( domMutations ) {
- // Use set for deduplication.
- const mutatedTexts = new Set();
- const mutatedElements = new Set();
- for ( let mutation of domMutations ) {
- if ( mutation.type === 'childList' ) {
- const element = ViewElement.getCorespondingElement( mutation.target );
- if ( element ) {
- mutatedElements.add( element );
- }
- }
- }
- for ( let mutation of domMutations ) {
- if ( mutation.type === 'characterData' ) {
- const text = ViewText.getCorespondingText( mutation.target );
- if ( text && !mutatedElements.has( text.parent ) ) {
- mutatedTexts.add( {
- type: 'text',
- oldText: text.getText(),
- newText: mutation.target.data,
- node: text
- } );
- }
- }
- }
- const viewMutations = [];
- for ( let mutatedText of mutatedTexts ) {
- mutatedText.node.markToSync( 'TEXT_NEEDS_UPDATE' );
- viewMutations.push( mutatedText );
- }
- for ( let viewElement of mutatedElements ) {
- const domElement = viewElement.domElement;
- const domChildren = domElement.childNodes;
- const viewChildren = viewElement.getChildren();
- const newViewChildren = [];
- for ( let domChild of domChildren ) {
- newViewChildren.push( ViewElement.createFromDom( domChild ) );
- }
- viewElement.markToSync( 'CHILDREN_NEED_UPDATE' );
- viewMutations.push( {
- type: 'childNodes',
- oldChildren: viewElement.getChildren(),
- newChildren: newViewChildren,
- diff: diff( viewChildren, newViewChildren, compareNodes ),
- node: viewElement
- } );
- }
- this.fire( 'mutations', viewMutations );
- this.treeView.render();
- function compareNodes( oldNode, newNode ) {
- // Elements.
- if ( oldNode instanceof ViewElement && newNode instanceof ViewElement ) {
- return oldNode === newNode;
- }
- // Texts.
- else if ( oldNode instanceof ViewText && newNode instanceof ViewText ) {
- return oldNode.getText() === newNode.getText();
- }
- // Not matching types.
- return false;
- }
- }
- }
- objectUtils.extend( MutationObserver.prototype, EmitterMixin );
|