1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5'use strict'; 6 7/** 8 * @fileoverview Container that decorates its children. 9 */ 10base.require('base.events'); 11base.require('ui'); 12 13base.exportTo('ui', function() { 14 /** 15 * @constructor 16 */ 17 var ContainerThatDecoratesItsChildren = ui.define('div'); 18 19 ContainerThatDecoratesItsChildren.prototype = { 20 __proto__: HTMLUnknownElement.prototype, 21 22 decorate: function() { 23 this.observer_ = new WebKitMutationObserver(this.didMutate_.bind(this)); 24 this.observer_.observe(this, { childList: true }); 25 26 // textContent is a variable on regular HTMLElements. However, we want to 27 // hook and prevent writes to it. 28 Object.defineProperty( 29 this, 'textContent', 30 { get: undefined, set: this.onSetTextContent_}); 31 }, 32 33 appendChild: function(x) { 34 HTMLUnknownElement.prototype.appendChild.call(this, x); 35 this.didMutate_(this.observer_.takeRecords()); 36 }, 37 38 insertBefore: function(x, y) { 39 HTMLUnknownElement.prototype.insertBefore.call(this, x, y); 40 this.didMutate_(this.observer_.takeRecords()); 41 }, 42 43 removeChild: function(x) { 44 HTMLUnknownElement.prototype.removeChild.call(this, x); 45 this.didMutate_(this.observer_.takeRecords()); 46 }, 47 48 replaceChild: function(x, y) { 49 HTMLUnknownElement.prototype.replaceChild.call(this, x, y); 50 this.didMutate_(this.observer_.takeRecords()); 51 }, 52 53 onSetTextContent_: function(textContent) { 54 if (textContent != '') 55 throw new Error('textContent can only be set to \'\'.'); 56 this.clear(); 57 }, 58 59 clear: function() { 60 while (this.lastChild) 61 HTMLUnknownElement.prototype.removeChild.call(this, this.lastChild); 62 this.didMutate_(this.observer_.takeRecords()); 63 }, 64 65 didMutate_: function(records) { 66 this.beginDecorating_(); 67 for (var i = 0; i < records.length; i++) { 68 var addedNodes = records[i].addedNodes; 69 if (addedNodes) { 70 for (var j = 0; j < addedNodes.length; j++) 71 this.decorateChild_(addedNodes[j]); 72 } 73 var removedNodes = records[i].removedNodes; 74 if (removedNodes) { 75 for (var j = 0; j < removedNodes.length; j++) { 76 this.undecorateChild_(removedNodes[j]); 77 } 78 } 79 } 80 this.doneDecoratingForNow_(); 81 }, 82 83 decorateChild_: function(child) { 84 throw new Error('Not implemented'); 85 }, 86 87 undecorateChild_: function(child) { 88 throw new Error('Not implemented'); 89 }, 90 91 beginDecorating_: function() { 92 }, 93 94 doneDecoratingForNow_: function() { 95 } 96 }; 97 98 return { 99 ContainerThatDecoratesItsChildren: ContainerThatDecoratesItsChildren 100 }; 101 102}); 103