inheritance - Sharing getter/setter functions across Javascript code -


the following example based off of mike bostock's reusable charts proposal.

given 2 functions (bar() , pie()) each generate different kind of chart:

function bar() {   var width = 720, // default width       height = 80; // default height    function my() {     console.log('bar created: ' + width + ' ' + height);   }    my.width = function(value) {     if (!arguments.length) return width;     width = value;     return my;   };    my.height = function(value) {     if (!arguments.length) return height;     height = value;     return my;   };    my.render = function() {     my();      return my;   };    return my; }  function pie() {   var width = 720, // default width       height = 80; // default height    function my() {     console.log('pie created: ' + width + ' ' + height);   }    my.width = function(value) {     if (!arguments.length) return width;     width = value;     return my;   };    my.height = function(value) {     if (!arguments.length) return height;     height = value;     return my;   };    my.render = function() {     my();      return my;   };    return my; } 

i can call these functions via chaining method such:

bar().width(200).render();  // bar created: 200 80 pie().height(300).render();  // pie created 720 300 

is there way code these getter , setter methods same? instance, plan on having width() functions in each of these exact same. how can make bar() , pie() functions inherit shared functions width(), height(), render()?

right... thing particular style of instantiating functions , hanging additional methods off of them variables have part of scope of function instantiates returned function (bar or pie). since variables internal , inaccessible outside of scope, there isn't way @ them when extending instance.

before going further, note implementation bit off. first, console.log('bar created: ' + width + ' ' + height);, semantically that's incorrect. that's not it's created, rather that's it's rendered. it's created when call bar().

then, when render chart, instead of bar().width(200).render() you're supposed is, e.g.

var barchart = bar().width(200);  d3.select('svg')   .append('g')   .call(barchart) 

you don't need render(). instead, body of my() render. but, per mbostocks suggestion, my() should take d3 selection param, in example g element being appended. right of of reusable charts tutorial linked to; re-read , you'll see mean.

finally, in answer actual question. way using d3.rebind. first have create common base class has internal width variable , width() getter/setter, so:

function base() {   var width;    function my(selection) {     console.log('base: ' + width);   }    my.width = function(value) {     if (!arguments.length) return width;     width = value;     return my;   };    return my; } 

next, want make bar (and pie) extend base, this:

function bar() {   var _base = base(); // instantiate _base, has width() method    function my(selection) {     // in here, if want width, call `_base.width()`     // and, if there's shared rendering functionality want     // put in base, can run `selection.call(_base)`   }    d3.rebind(my, _base, 'width'); // make width() function of   return my; } 

the last line, copies width() my can call bar().width(). here's fiddle works.


Comments

Popular posts from this blog

javascript - RequestAnimationFrame not working when exiting fullscreen switching space on Safari -

jsf - How to ajax update an item in the footer of a PrimeFaces dataTable? -

django - CSRF verification failed. Request aborted. CSRF cookie not set -