diff --git a/package-res/ccc/core/base/chart/chart.js b/package-res/ccc/core/base/chart/chart.js index cbcda517f..38dbe165a 100644 --- a/package-res/ccc/core/base/chart/chart.js +++ b/package-res/ccc/core/base/chart/chart.js @@ -227,9 +227,6 @@ def if(isRootInit) { this._processDataOptions(this.options); - // Now's a good time as any other to clear out all tipsy tooltips - pvc.removeTipsyLegends(); - // Any data exists or throws // (must be done AFTER processing options // because of width, height properties and noData extension point...) @@ -607,11 +604,12 @@ def try { this.useTextMeasureCache(function() { try { - while(true) { + while(true) { + if(!this.parent && this.isCreated) + pvc.removeTipsyLegends(); + if(!this.isCreated || recreate) this._create({reloadData: reloadData}); - else if(!this.parent && this.isCreated) - pvc.removeTipsyLegends(); // TODO: Currently, the following always redirects the call // to topRoot.render; diff --git a/package-res/lib/protovis.js b/package-res/lib/protovis.js index 5529fcde2..acd4f608b 100644 --- a/package-res/lib/protovis.js +++ b/package-res/lib/protovis.js @@ -11,7 +11,7 @@ * the license for the specific language governing your rights and limitations. */ /*! Copyright 2010 Stanford Visualization Group, Mike Bostock, BSD license. */ - /*! b3bcf01fff70f1fcad2464fa4a700c22f9ed4596 */ + /*! 0a846e02116638f4d7f3c88a223ee1ae23f0cb3f */ /** * @class The built-in Array class. * @name Array @@ -11692,17 +11692,25 @@ pv.Mark.prototype.setPropertyValue = function(name, v, isDef, cast, chain, tag){ id: pv.id(), value: v, type: type, - tag: tag + tag: tag, + proto: null, + root: null, + + // Used in #bind to connect the property chains + // found along a mark's proto chain. + _proto: null }; + + p.root = p; - var specified = propertiesMap[name]; + var existing = propertiesMap[name]; propertiesMap[name] = p; - if(specified) { + if(existing) { // Find it and remove it for(var i = 0, P = properties.length; i < P; i++) { - if(properties[i] === specified) { + if(properties[i] === existing) { properties.splice(i, 1); break; } @@ -11711,9 +11719,9 @@ pv.Mark.prototype.setPropertyValue = function(name, v, isDef, cast, chain, tag){ properties.push(p); - if(chain && specified && type === 3) { // is a prop fun - p.proto = specified; - p.root = specified.root || specified; + if(chain && existing && type === 3) { // is a prop fun + p.proto = existing; + p.root = existing.root; } return p; @@ -12482,6 +12490,7 @@ pv.Mark.prototype.renderCore = function() { */ pv.Mark.prototype.bind = function() { var seen = {}, + root = {}, data, // Required props (no defs) @@ -12525,20 +12534,23 @@ pv.Mark.prototype.bind = function() { var pLeaf = seen[name]; if(!pLeaf) { seen[name] = p; + root[name] = p.root; + // Reset, from a previous binding + p.root._proto = null; switch(name) { case 'data': data = p; break; case 'visible': case 'id': required.push(p); break; default: types[p.type].push(p); break; } - } else if(pLeaf.type === 3) { // prop/fun - // Chain properties - // - // seen[name]-> (leaf).proto-> (B).proto-> (C).proto-> (root) - // .root-------------------------------^ - var pRoot = pLeaf.root; - pLeaf.root = p; - if(!pRoot) { pLeaf.proto = p; } - else if(!pRoot.proto) { pRoot.proto = p; } + } else { + var pRoot = root[name]; + if(pRoot.type === 3) { // prop/fun + // Chain property chains of pRoot and p + pRoot._proto = p; + pRoot = root[name] = p.root; + // Reset, from a previous binding + pRoot._proto = null; + } } } } while((mark = mark.proto)); @@ -12781,7 +12793,7 @@ pv.Mark.prototype.buildInstance = function(s) { // 3 - prop - fun function(p) { - _protoProp = p.proto; + _protoProp = p.proto || p._proto; return p.value.apply(this, _stack); } ]; @@ -22675,12 +22687,11 @@ pv.Behavior.point = function(keyArgs) { // Initialize panel. // Unpoint when the mouse leaves the pointing panel. - if(!pointingPanel && this.type === 'panel') { - + if(pointingPanel) { + ; + } else if(this.type === 'panel') { pointingPanel = this; - pointingPanel.event('mouseout', function() { - mouseout.call(pointingPanel.scene.$g); - }); + this.event('mouseout', function() { mouseout.call(this.scene.$g); }); if(stealClick) pointingPanel.addEventInterceptor('click', eventInterceptor); } else { diff --git a/package-res/lib/tipsy.js b/package-res/lib/tipsy.js index 7bc6f3533..52f1dd244 100644 --- a/package-res/lib/tipsy.js +++ b/package-res/lib/tipsy.js @@ -40,7 +40,7 @@ $canvas, _isEnabledFun = opts.isEnabled, _sharedTipsyInfo; - + function getTooltipText() { var instance = _mark.instance(); var title = @@ -292,7 +292,7 @@ // in pv context function createTipsy(mark) { - if(_tip.debug >= 20) _tip.log("[TIPSY] #" + _tipsyId + " Creating"); + if(_tip.debug >= 20) _tip.log("[TIPSY] #" + _tipsyId + " Creating _id=" + _id); var c = mark.root.canvas(); @@ -316,8 +316,11 @@ /*global document:true*/ var fakeTipTarget = document.getElementById(_id); if(!fakeTipTarget) { + if(_tip.debug >= 20) _tip.log("[TIPSY] #" + _tipsyId + " Creating Fake Tip Target=" + _id); + fakeTipTarget = document.createElement("div"); fakeTipTarget.id = _id; + fakeTipTarget.className = "fakeTipsyTarget"; c.appendChild(fakeTipTarget); } @@ -360,19 +363,19 @@ var createId = ($canvas[0].$pvCreateId || 0); if(_sharedTipsyInfo.createId === createId){ - _sharedTipsyInfo.behaviors.push(hideTipsyOther); + _sharedTipsyInfo.behaviors.push(disposeTipsy); return; } // Protovis has recreated the whole structure // So all existing tipsies (but this one) are invalid... // Hide them and let GC do the rest - _sharedTipsyInfo.behaviors.forEach(function(hideTipsyFun) { hideTipsyFun(); }); + _sharedTipsyInfo.behaviors.forEach(function(dispose) { dispose(); }); } _sharedTipsyInfo = { createId: ($canvas[0].$pvCreateId || 0), - behaviors: [hideTipsyOther] + behaviors: [disposeTipsy] }; $canvas.data('tipsy-pv-shared-info', _sharedTipsyInfo); @@ -480,8 +483,8 @@ if(changedTargetElem) { if($targetElem) { - $targetElem.unbind('mousemove', onTargetElemMouseMove); - $targetElem.unbind('mouseleave', hideTipsy); + $targetElem.off('mousemove', onTargetElemMouseMove); + $targetElem.off('mouseleave', hideTipsy); } $targetElem = targetElem ? $(targetElem) : null; @@ -548,13 +551,28 @@ if(_tip.debug >= 20) _tip.log("[TIPSY] #" + _tipsyId + " Hiding Immediately opId=" + opId); hideTipsyCore(opId); } - + + function disposeTipsy() { + if(_tip.debug >= 20) _tip.log("[TIPSY] #" + _tipsyId + " Disposing"); + hideTipsyOther(); + if($fakeTipTarget) { + $fakeTipTarget.data("tipsy", null); + $fakeTipTarget.each(function(elem) { elem.$tooltipOptions = null; }); + $fakeTipTarget.remove(); + $fakeTipTarget = null; + } + if($canvas) { + $canvas.off('mouseleave', hideTipsy); + $canvas = null; + } + } + function hideTipsyOther() { var opId = getNewOperationId(); if(_tip.debug >= 20) _tip.log("[TIPSY] #" + _tipsyId + " Hiding as Other opId=" + opId); hideTipsyCore(opId); } - + function hideTipsyCore(opId) { // Uncomment to debug the tooltip markup. // Leaves the tooltip visible.