<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.extremist.software/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=209.10.200.2</id>
	<title>Noisebridge - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.extremist.software/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=209.10.200.2"/>
	<link rel="alternate" type="text/html" href="https://wiki.extremist.software/wiki/Special:Contributions/209.10.200.2"/>
	<updated>2026-04-05T16:56:32Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.13</generator>
	<entry>
		<id>https://wiki.extremist.software/index.php?title=JavaScript/Notes/PrivateProxy&amp;diff=42591</id>
		<title>JavaScript/Notes/PrivateProxy</title>
		<link rel="alternate" type="text/html" href="https://wiki.extremist.software/index.php?title=JavaScript/Notes/PrivateProxy&amp;diff=42591"/>
		<updated>2014-05-19T20:48:07Z</updated>

		<summary type="html">&lt;p&gt;209.10.200.2: /* Object Oriented Design */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Proxy == &lt;br /&gt;
A proxy is as an interface to something else.&lt;br /&gt;
&lt;br /&gt;
== Private Proxy == &lt;br /&gt;
A public interface object delegates some of its responsibility to a private instance in the same scope.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Structural Pattern:&#039;&#039;&#039; The private and public instances are &amp;lt;dfn&amp;gt;tightly coupled&amp;lt;/dfn&amp;gt;. They share data with each other only within the scope where they are defined. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Usage:&#039;&#039;&#039; Details and complexities of the underlying object must be hidden. By exposing a very limited set of methods, the public interface offers little opportunity to modify and break its corresponding private counterpart.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039; User wants to be able to interact with &amp;quot;program&amp;quot; objects on a calendar. The &amp;lt;dfn&amp;gt;program&amp;lt;/dfn&amp;gt; can be then modified by the user.&lt;br /&gt;
&lt;br /&gt;
The application handles modification of program objects through a &amp;lt;dfn&amp;gt;ProgramProxy&amp;lt;/dfn&amp;gt;, by calling &amp;lt;dfn&amp;gt;setPhases&amp;lt;/dfn&amp;gt;, &amp;lt;dfn&amp;gt;setCampaigns&amp;lt;/dfn&amp;gt;. The client of the API may call &amp;lt;dfn&amp;gt;buildHTML&amp;lt;/dfn&amp;gt; to generate new HTML for the program or &amp;lt;dfn&amp;gt;toJSON&amp;lt;/dfn&amp;gt; to get a JSON representation of it. &lt;br /&gt;
&lt;br /&gt;
=== Alternatives === &lt;br /&gt;
The popular alternative to this approach is MVC with libraries such as Backbone, YUI app framework, Meteor, or Angular, most of which use Handlebars. &lt;br /&gt;
&lt;br /&gt;
Prefabricated solutions can work, in the general sense. But they often entail creating a much larger codebase with less specificity to the design of the application. These frameworks, while commonly used, add the complexity of adapting your application&#039;s logic to their framework (shoehorning). Being so generalized, they generally fail to address specific problem effectively.&lt;br /&gt;
&lt;br /&gt;
Such interdependent, large libraries introduce inevitable bugs and memory leaks that can be extremely difficult to track down, harder yet to patch, and with patches might never get merged into the existing codebase.&lt;br /&gt;
&lt;br /&gt;
=== Object Oriented Design === &lt;br /&gt;
Design patterns are not frameworks. A design pattern is any reusable solution to a type problem in a given context. &#039;&#039;Any&#039;&#039; elegant solution therefore depends on the problem at hand (and not the other way around). Although this architectural pattern depicts the architecture, it is not an architecture.&lt;br /&gt;
&lt;br /&gt;
It thus follows that the PrivateProxy presented can be a solution for some sorts of problems, but cannot be the Answer to Solve our Problems, in the general sense.&lt;br /&gt;
&lt;br /&gt;
== Code Example == &lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var Program = function(A) {&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;use strict&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  var phaseListClassName = &amp;quot;program-phase-list&amp;quot;,&lt;br /&gt;
      phaseClassName = &amp;quot;program-phase&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  function Program(id, config) {&lt;br /&gt;
    var start = config.startDate,&lt;br /&gt;
        end = config.endDate;&lt;br /&gt;
    this.id = id;&lt;br /&gt;
    this.dateRange = new A.DateRange(start, end);&lt;br /&gt;
    this.phases = config.phases.slice();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  var programs = {},&lt;br /&gt;
      programProxies = {};&lt;br /&gt;
&lt;br /&gt;
  var phaseListElement = document.createElement(&amp;quot;ul&amp;quot;),&lt;br /&gt;
      phaseElement = document.createElement(&amp;quot;li&amp;quot;);&lt;br /&gt;
  phaseListElement.className = phaseListClassName;&lt;br /&gt;
  phaseElement.className = phaseClassName;&lt;br /&gt;
&lt;br /&gt;
  function ProgramProxy(id, config) {&lt;br /&gt;
    this.id = id;&lt;br /&gt;
    this.start = config.startDate;&lt;br /&gt;
    this.displayName = config.name;&lt;br /&gt;
    this.end = config.endDate;&lt;br /&gt;
    programs[id] = new Program(id, config);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  ProgramProxy.prototype = {&lt;br /&gt;
    setPhases: function(phases) {&lt;br /&gt;
      if(phases &amp;amp;&amp;amp; phases.slice) {&lt;br /&gt;
        programs[this.id].phases = phases.slice();&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    buildHTML: function() {&lt;br /&gt;
      var program = programs[this.id],&lt;br /&gt;
          html = &amp;quot;&amp;quot;;&lt;br /&gt;
      html += buildPhaseHTML(program);&lt;br /&gt;
      html += buildCampaignHTML(program);&lt;br /&gt;
      return html;&lt;br /&gt;
    }&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  var div = document.createElement(&amp;quot;div&amp;quot;);&lt;br /&gt;
  function buildPhaseHTML(program) {&lt;br /&gt;
    div.innerHTML = &amp;quot;&amp;quot;;&lt;br /&gt;
    var i, li,&lt;br /&gt;
        phases = program.phases,&lt;br /&gt;
        len = phases.length,&lt;br /&gt;
        phaseRationalValue,&lt;br /&gt;
        ul = phaseListElement.cloneNode(false);&lt;br /&gt;
    ul.id = &amp;quot;program-&amp;quot; + program.id;&lt;br /&gt;
    for(i = 0; i &amp;lt; len; i++) {&lt;br /&gt;
      li = phaseElement.cloneNode(false);&lt;br /&gt;
      li.id = &amp;quot;program-&amp;quot;&lt;br /&gt;
            + program.id &lt;br /&gt;
            + &amp;quot;-phase-&amp;quot;&lt;br /&gt;
            + phases[i].name  &lt;br /&gt;
            + &amp;quot;&amp;quot;;&lt;br /&gt;
      li.style.width = &lt;br /&gt;
        getPhaseWidth(phases[i], program.dateRange.duration);&lt;br /&gt;
      ul.appendChild(li);&lt;br /&gt;
    }&lt;br /&gt;
    div.appendChild(ul);&lt;br /&gt;
    return div.innerHTML;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  function buildCampaignHTML() {&lt;br /&gt;
    return&amp;quot;&amp;quot;;&lt;br /&gt;
  &amp;quot;&amp;lt;ul&amp;gt;&amp;quot;&lt;br /&gt;
    + &amp;quot;&amp;lt;li&amp;gt;fixme:\u00A0buildCampaignHTML&amp;quot;&lt;br /&gt;
    + &amp;quot;&amp;lt;/ul&amp;gt;&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function getPhaseWidth(phase, programDuration) {&lt;br /&gt;
    var phaseDateRange = new A.DateRange(&lt;br /&gt;
      phase.startDate, phase.endDate);&lt;br /&gt;
    var rationalValue = phaseDateRange.duration/programDuration;&lt;br /&gt;
    return (0|100 * rationalValue) + &amp;quot;%&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function getOrCreateProgram(config) {&lt;br /&gt;
    return programProxies[config.id] || &lt;br /&gt;
      (programProxies[config.id] = new ProgramProxy(config.id, config));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function removeProgram(id) {&lt;br /&gt;
    if(!programs[id]) {&lt;br /&gt;
      throw new ReferenceError(&amp;quot;Program: &amp;quot; &lt;br /&gt;
        + id&lt;br /&gt;
        + &amp;quot; does not exist.&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
    delete programs[id];&lt;br /&gt;
    delete programProxies[id];&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return {&lt;br /&gt;
    getOrCreate: getOrCreateProgram,&lt;br /&gt;
    remove: removeProgram&lt;br /&gt;
  };&lt;br /&gt;
}({&lt;br /&gt;
  DateRange: DateRange // defined elsewhere.&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Program.getOrCreate&amp;lt;/code&amp;gt; returns a &amp;lt;code&amp;gt;ProgramProxy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ProgramProxy&amp;lt;/code&amp;gt; has two methods, both of which delegate to &amp;lt;code&amp;gt;Program&amp;lt;/code&amp;gt; instances. &lt;br /&gt;
&lt;br /&gt;
The body of buildHTML:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
setPhases: function(phases) {&lt;br /&gt;
 if(phases &amp;amp;&amp;amp; phases.slice) {&lt;br /&gt;
    programs[id].phases = phases.slice();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Because each &amp;lt;code&amp;gt;ProgramProxy&amp;lt;/code&amp;gt; instance has a corresponding &amp;lt;code&amp;gt;Program&amp;lt;/code&amp;gt; instance with the same id, any &amp;lt;code&amp;gt;ProgramProxy&amp;lt;/code&amp;gt; or can access its &amp;lt;code&amp;gt;Program&amp;lt;/code&amp;gt; instance counterpart from within any of its instance methods, and vice versa.&lt;br /&gt;
&lt;br /&gt;
This shared instance access is possible because both &amp;lt;code&amp;gt;Program&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ProgramProxy&amp;lt;/code&amp;gt; instances being stored in a corresponding object for, keyed by id. Ideally, this would be implemented in a WeakMap.&lt;br /&gt;
&lt;br /&gt;
See also: [http://sourcemaking.com/design_patterns/proxy Proxy Design Pattern].&lt;/div&gt;</summary>
		<author><name>209.10.200.2</name></author>
	</entry>
	<entry>
		<id>https://wiki.extremist.software/index.php?title=JavaScript/Notes/PrivateProxy&amp;diff=42590</id>
		<title>JavaScript/Notes/PrivateProxy</title>
		<link rel="alternate" type="text/html" href="https://wiki.extremist.software/index.php?title=JavaScript/Notes/PrivateProxy&amp;diff=42590"/>
		<updated>2014-05-19T20:17:53Z</updated>

		<summary type="html">&lt;p&gt;209.10.200.2: /* Alternatives */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Proxy == &lt;br /&gt;
A proxy is as an interface to something else.&lt;br /&gt;
&lt;br /&gt;
== Private Proxy == &lt;br /&gt;
A public interface object delegates some of its responsibility to a private instance in the same scope.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Structural Pattern:&#039;&#039;&#039; The private and public instances are &amp;lt;dfn&amp;gt;tightly coupled&amp;lt;/dfn&amp;gt;. They share data with each other only within the scope where they are defined. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Usage:&#039;&#039;&#039; Details and complexities of the underlying object must be hidden. By exposing a very limited set of methods, the public interface offers little opportunity to modify and break its corresponding private counterpart.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039; User wants to be able to interact with &amp;quot;program&amp;quot; objects on a calendar. The &amp;lt;dfn&amp;gt;program&amp;lt;/dfn&amp;gt; can be then modified by the user.&lt;br /&gt;
&lt;br /&gt;
The application handles modification of program objects through a &amp;lt;dfn&amp;gt;ProgramProxy&amp;lt;/dfn&amp;gt;, by calling &amp;lt;dfn&amp;gt;setPhases&amp;lt;/dfn&amp;gt;, &amp;lt;dfn&amp;gt;setCampaigns&amp;lt;/dfn&amp;gt;. The client of the API may call &amp;lt;dfn&amp;gt;buildHTML&amp;lt;/dfn&amp;gt; to generate new HTML for the program or &amp;lt;dfn&amp;gt;toJSON&amp;lt;/dfn&amp;gt; to get a JSON representation of it. &lt;br /&gt;
&lt;br /&gt;
=== Alternatives === &lt;br /&gt;
The popular alternative to this approach is MVC with libraries such as Backbone, YUI app framework, Meteor, or Angular, most of which use Handlebars. &lt;br /&gt;
&lt;br /&gt;
Prefabricated solutions can work, in the general sense. But they often entail creating a much larger codebase with less specificity to the design of the application. These frameworks, while commonly used, add the complexity of adapting your application&#039;s logic to their framework (shoehorning). Being so generalized, they generally fail to address specific problem effectively.&lt;br /&gt;
&lt;br /&gt;
Such interdependent, large libraries introduce inevitable bugs and memory leaks that can be extremely difficult to track down, harder yet to patch, and with patches might never get merged into the existing codebase.&lt;br /&gt;
&lt;br /&gt;
=== Object Oriented Design === &lt;br /&gt;
Design patterns are not frameworks. A design pattern is any reusable solution to a type problem in a given context. &#039;&#039;All&#039;&#039; elegant solution therefore depends on the problem at hand (and not the other way around). Although this architectural pattern depicts the architecture, it is not an architecture.&lt;br /&gt;
&lt;br /&gt;
It thus follows that the PrivateProxy presented can be a solution for some sorts of problems, but cannot be the Answer to Solve our Problems, in the general sense.&lt;br /&gt;
&lt;br /&gt;
== Code Example == &lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var Program = function(A) {&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;use strict&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  var phaseListClassName = &amp;quot;program-phase-list&amp;quot;,&lt;br /&gt;
      phaseClassName = &amp;quot;program-phase&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  function Program(id, config) {&lt;br /&gt;
    var start = config.startDate,&lt;br /&gt;
        end = config.endDate;&lt;br /&gt;
    this.id = id;&lt;br /&gt;
    this.dateRange = new A.DateRange(start, end);&lt;br /&gt;
    this.phases = config.phases.slice();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  var programs = {},&lt;br /&gt;
      programProxies = {};&lt;br /&gt;
&lt;br /&gt;
  var phaseListElement = document.createElement(&amp;quot;ul&amp;quot;),&lt;br /&gt;
      phaseElement = document.createElement(&amp;quot;li&amp;quot;);&lt;br /&gt;
  phaseListElement.className = phaseListClassName;&lt;br /&gt;
  phaseElement.className = phaseClassName;&lt;br /&gt;
&lt;br /&gt;
  function ProgramProxy(id, config) {&lt;br /&gt;
    this.id = id;&lt;br /&gt;
    this.start = config.startDate;&lt;br /&gt;
    this.displayName = config.name;&lt;br /&gt;
    this.end = config.endDate;&lt;br /&gt;
    programs[id] = new Program(id, config);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  ProgramProxy.prototype = {&lt;br /&gt;
    setPhases: function(phases) {&lt;br /&gt;
      if(phases &amp;amp;&amp;amp; phases.slice) {&lt;br /&gt;
        programs[this.id].phases = phases.slice();&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    buildHTML: function() {&lt;br /&gt;
      var program = programs[this.id],&lt;br /&gt;
          html = &amp;quot;&amp;quot;;&lt;br /&gt;
      html += buildPhaseHTML(program);&lt;br /&gt;
      html += buildCampaignHTML(program);&lt;br /&gt;
      return html;&lt;br /&gt;
    }&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  var div = document.createElement(&amp;quot;div&amp;quot;);&lt;br /&gt;
  function buildPhaseHTML(program) {&lt;br /&gt;
    div.innerHTML = &amp;quot;&amp;quot;;&lt;br /&gt;
    var i, li,&lt;br /&gt;
        phases = program.phases,&lt;br /&gt;
        len = phases.length,&lt;br /&gt;
        phaseRationalValue,&lt;br /&gt;
        ul = phaseListElement.cloneNode(false);&lt;br /&gt;
    ul.id = &amp;quot;program-&amp;quot; + program.id;&lt;br /&gt;
    for(i = 0; i &amp;lt; len; i++) {&lt;br /&gt;
      li = phaseElement.cloneNode(false);&lt;br /&gt;
      li.id = &amp;quot;program-&amp;quot;&lt;br /&gt;
            + program.id &lt;br /&gt;
            + &amp;quot;-phase-&amp;quot;&lt;br /&gt;
            + phases[i].name  &lt;br /&gt;
            + &amp;quot;&amp;quot;;&lt;br /&gt;
      li.style.width = &lt;br /&gt;
        getPhaseWidth(phases[i], program.dateRange.duration);&lt;br /&gt;
      ul.appendChild(li);&lt;br /&gt;
    }&lt;br /&gt;
    div.appendChild(ul);&lt;br /&gt;
    return div.innerHTML;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  function buildCampaignHTML() {&lt;br /&gt;
    return&amp;quot;&amp;quot;;&lt;br /&gt;
  &amp;quot;&amp;lt;ul&amp;gt;&amp;quot;&lt;br /&gt;
    + &amp;quot;&amp;lt;li&amp;gt;fixme:\u00A0buildCampaignHTML&amp;quot;&lt;br /&gt;
    + &amp;quot;&amp;lt;/ul&amp;gt;&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function getPhaseWidth(phase, programDuration) {&lt;br /&gt;
    var phaseDateRange = new A.DateRange(&lt;br /&gt;
      phase.startDate, phase.endDate);&lt;br /&gt;
    var rationalValue = phaseDateRange.duration/programDuration;&lt;br /&gt;
    return (0|100 * rationalValue) + &amp;quot;%&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function getOrCreateProgram(config) {&lt;br /&gt;
    return programProxies[config.id] || &lt;br /&gt;
      (programProxies[config.id] = new ProgramProxy(config.id, config));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function removeProgram(id) {&lt;br /&gt;
    if(!programs[id]) {&lt;br /&gt;
      throw new ReferenceError(&amp;quot;Program: &amp;quot; &lt;br /&gt;
        + id&lt;br /&gt;
        + &amp;quot; does not exist.&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
    delete programs[id];&lt;br /&gt;
    delete programProxies[id];&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return {&lt;br /&gt;
    getOrCreate: getOrCreateProgram,&lt;br /&gt;
    remove: removeProgram&lt;br /&gt;
  };&lt;br /&gt;
}({&lt;br /&gt;
  DateRange: DateRange // defined elsewhere.&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Program.getOrCreate&amp;lt;/code&amp;gt; returns a &amp;lt;code&amp;gt;ProgramProxy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ProgramProxy&amp;lt;/code&amp;gt; has two methods, both of which delegate to &amp;lt;code&amp;gt;Program&amp;lt;/code&amp;gt; instances. &lt;br /&gt;
&lt;br /&gt;
The body of buildHTML:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
setPhases: function(phases) {&lt;br /&gt;
 if(phases &amp;amp;&amp;amp; phases.slice) {&lt;br /&gt;
    programs[id].phases = phases.slice();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Because each &amp;lt;code&amp;gt;ProgramProxy&amp;lt;/code&amp;gt; instance has a corresponding &amp;lt;code&amp;gt;Program&amp;lt;/code&amp;gt; instance with the same id, any &amp;lt;code&amp;gt;ProgramProxy&amp;lt;/code&amp;gt; or can access its &amp;lt;code&amp;gt;Program&amp;lt;/code&amp;gt; instance counterpart from within any of its instance methods, and vice versa.&lt;br /&gt;
&lt;br /&gt;
This shared instance access is possible because both &amp;lt;code&amp;gt;Program&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ProgramProxy&amp;lt;/code&amp;gt; instances being stored in a corresponding object for, keyed by id. Ideally, this would be implemented in a WeakMap.&lt;br /&gt;
&lt;br /&gt;
See also: [http://sourcemaking.com/design_patterns/proxy Proxy Design Pattern].&lt;/div&gt;</summary>
		<author><name>209.10.200.2</name></author>
	</entry>
	<entry>
		<id>https://wiki.extremist.software/index.php?title=JavaScript/Notes/PrivateProxy&amp;diff=42589</id>
		<title>JavaScript/Notes/PrivateProxy</title>
		<link rel="alternate" type="text/html" href="https://wiki.extremist.software/index.php?title=JavaScript/Notes/PrivateProxy&amp;diff=42589"/>
		<updated>2014-05-19T20:08:28Z</updated>

		<summary type="html">&lt;p&gt;209.10.200.2: /* Alternatives */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Proxy == &lt;br /&gt;
A proxy is as an interface to something else.&lt;br /&gt;
&lt;br /&gt;
== Private Proxy == &lt;br /&gt;
A public interface object delegates some of its responsibility to a private instance in the same scope.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Structural Pattern:&#039;&#039;&#039; The private and public instances are &amp;lt;dfn&amp;gt;tightly coupled&amp;lt;/dfn&amp;gt;. They share data with each other only within the scope where they are defined. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Usage:&#039;&#039;&#039; Details and complexities of the underlying object must be hidden. By exposing a very limited set of methods, the public interface offers little opportunity to modify and break its corresponding private counterpart.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Example:&#039;&#039;&#039; User wants to be able to interact with &amp;quot;program&amp;quot; objects on a calendar. The &amp;lt;dfn&amp;gt;program&amp;lt;/dfn&amp;gt; can be then modified by the user.&lt;br /&gt;
&lt;br /&gt;
The application handles modification of program objects through a &amp;lt;dfn&amp;gt;ProgramProxy&amp;lt;/dfn&amp;gt;, by calling &amp;lt;dfn&amp;gt;setPhases&amp;lt;/dfn&amp;gt;, &amp;lt;dfn&amp;gt;setCampaigns&amp;lt;/dfn&amp;gt;. The client of the API may call &amp;lt;dfn&amp;gt;buildHTML&amp;lt;/dfn&amp;gt; to generate new HTML for the program or &amp;lt;dfn&amp;gt;toJSON&amp;lt;/dfn&amp;gt; to get a JSON representation of it. &lt;br /&gt;
&lt;br /&gt;
=== Alternatives === &lt;br /&gt;
The popular alternative to this approach is MVC with libraries such as Backbone, YUI app framework, Meteor, or Angular. &lt;br /&gt;
&lt;br /&gt;
Prefabricated solutions can work, in the general sense. But they often entail creating a much larger codebase with less specificity to the design of the application. These frameworks, while commonly used, add the complexity of adapting your application&#039;s logic to their framework (shoehorning). Being so generalized, they generally fail to address specific problem effectively.&lt;br /&gt;
&lt;br /&gt;
Such interdependent, large libraries introduce inevitable bugs and memory leaks that can be extremely difficult to track down, harder yet to patch, and with patches might never get merged into the existing codebase.&lt;br /&gt;
&lt;br /&gt;
=== Object Oriented Design === &lt;br /&gt;
Design patterns are not frameworks. A design pattern is any reusable solution to a type problem in a given context. &#039;&#039;All&#039;&#039; elegant solution therefore depends on the problem at hand (and not the other way around). Although this architectural pattern depicts the architecture, it is not an architecture.&lt;br /&gt;
&lt;br /&gt;
It thus follows that the PrivateProxy presented can be a solution for some sorts of problems, but cannot be the Answer to Solve our Problems, in the general sense.&lt;br /&gt;
&lt;br /&gt;
== Code Example == &lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var Program = function(A) {&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;use strict&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  var phaseListClassName = &amp;quot;program-phase-list&amp;quot;,&lt;br /&gt;
      phaseClassName = &amp;quot;program-phase&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  function Program(id, config) {&lt;br /&gt;
    var start = config.startDate,&lt;br /&gt;
        end = config.endDate;&lt;br /&gt;
    this.id = id;&lt;br /&gt;
    this.dateRange = new A.DateRange(start, end);&lt;br /&gt;
    this.phases = config.phases.slice();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  var programs = {},&lt;br /&gt;
      programProxies = {};&lt;br /&gt;
&lt;br /&gt;
  var phaseListElement = document.createElement(&amp;quot;ul&amp;quot;),&lt;br /&gt;
      phaseElement = document.createElement(&amp;quot;li&amp;quot;);&lt;br /&gt;
  phaseListElement.className = phaseListClassName;&lt;br /&gt;
  phaseElement.className = phaseClassName;&lt;br /&gt;
&lt;br /&gt;
  function ProgramProxy(id, config) {&lt;br /&gt;
    this.id = id;&lt;br /&gt;
    this.start = config.startDate;&lt;br /&gt;
    this.displayName = config.name;&lt;br /&gt;
    this.end = config.endDate;&lt;br /&gt;
    programs[id] = new Program(id, config);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  ProgramProxy.prototype = {&lt;br /&gt;
    setPhases: function(phases) {&lt;br /&gt;
      if(phases &amp;amp;&amp;amp; phases.slice) {&lt;br /&gt;
        programs[this.id].phases = phases.slice();&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    buildHTML: function() {&lt;br /&gt;
      var program = programs[this.id],&lt;br /&gt;
          html = &amp;quot;&amp;quot;;&lt;br /&gt;
      html += buildPhaseHTML(program);&lt;br /&gt;
      html += buildCampaignHTML(program);&lt;br /&gt;
      return html;&lt;br /&gt;
    }&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  var div = document.createElement(&amp;quot;div&amp;quot;);&lt;br /&gt;
  function buildPhaseHTML(program) {&lt;br /&gt;
    div.innerHTML = &amp;quot;&amp;quot;;&lt;br /&gt;
    var i, li,&lt;br /&gt;
        phases = program.phases,&lt;br /&gt;
        len = phases.length,&lt;br /&gt;
        phaseRationalValue,&lt;br /&gt;
        ul = phaseListElement.cloneNode(false);&lt;br /&gt;
    ul.id = &amp;quot;program-&amp;quot; + program.id;&lt;br /&gt;
    for(i = 0; i &amp;lt; len; i++) {&lt;br /&gt;
      li = phaseElement.cloneNode(false);&lt;br /&gt;
      li.id = &amp;quot;program-&amp;quot;&lt;br /&gt;
            + program.id &lt;br /&gt;
            + &amp;quot;-phase-&amp;quot;&lt;br /&gt;
            + phases[i].name  &lt;br /&gt;
            + &amp;quot;&amp;quot;;&lt;br /&gt;
      li.style.width = &lt;br /&gt;
        getPhaseWidth(phases[i], program.dateRange.duration);&lt;br /&gt;
      ul.appendChild(li);&lt;br /&gt;
    }&lt;br /&gt;
    div.appendChild(ul);&lt;br /&gt;
    return div.innerHTML;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  function buildCampaignHTML() {&lt;br /&gt;
    return&amp;quot;&amp;quot;;&lt;br /&gt;
  &amp;quot;&amp;lt;ul&amp;gt;&amp;quot;&lt;br /&gt;
    + &amp;quot;&amp;lt;li&amp;gt;fixme:\u00A0buildCampaignHTML&amp;quot;&lt;br /&gt;
    + &amp;quot;&amp;lt;/ul&amp;gt;&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function getPhaseWidth(phase, programDuration) {&lt;br /&gt;
    var phaseDateRange = new A.DateRange(&lt;br /&gt;
      phase.startDate, phase.endDate);&lt;br /&gt;
    var rationalValue = phaseDateRange.duration/programDuration;&lt;br /&gt;
    return (0|100 * rationalValue) + &amp;quot;%&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function getOrCreateProgram(config) {&lt;br /&gt;
    return programProxies[config.id] || &lt;br /&gt;
      (programProxies[config.id] = new ProgramProxy(config.id, config));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function removeProgram(id) {&lt;br /&gt;
    if(!programs[id]) {&lt;br /&gt;
      throw new ReferenceError(&amp;quot;Program: &amp;quot; &lt;br /&gt;
        + id&lt;br /&gt;
        + &amp;quot; does not exist.&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
    delete programs[id];&lt;br /&gt;
    delete programProxies[id];&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return {&lt;br /&gt;
    getOrCreate: getOrCreateProgram,&lt;br /&gt;
    remove: removeProgram&lt;br /&gt;
  };&lt;br /&gt;
}({&lt;br /&gt;
  DateRange: DateRange // defined elsewhere.&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;Program.getOrCreate&amp;lt;/code&amp;gt; returns a &amp;lt;code&amp;gt;ProgramProxy&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;ProgramProxy&amp;lt;/code&amp;gt; has two methods, both of which delegate to &amp;lt;code&amp;gt;Program&amp;lt;/code&amp;gt; instances. &lt;br /&gt;
&lt;br /&gt;
The body of buildHTML:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
setPhases: function(phases) {&lt;br /&gt;
 if(phases &amp;amp;&amp;amp; phases.slice) {&lt;br /&gt;
    programs[id].phases = phases.slice();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Because each &amp;lt;code&amp;gt;ProgramProxy&amp;lt;/code&amp;gt; instance has a corresponding &amp;lt;code&amp;gt;Program&amp;lt;/code&amp;gt; instance with the same id, any &amp;lt;code&amp;gt;ProgramProxy&amp;lt;/code&amp;gt; or can access its &amp;lt;code&amp;gt;Program&amp;lt;/code&amp;gt; instance counterpart from within any of its instance methods, and vice versa.&lt;br /&gt;
&lt;br /&gt;
This shared instance access is possible because both &amp;lt;code&amp;gt;Program&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ProgramProxy&amp;lt;/code&amp;gt; instances being stored in a corresponding object for, keyed by id. Ideally, this would be implemented in a WeakMap.&lt;br /&gt;
&lt;br /&gt;
See also: [http://sourcemaking.com/design_patterns/proxy Proxy Design Pattern].&lt;/div&gt;</summary>
		<author><name>209.10.200.2</name></author>
	</entry>
	<entry>
		<id>https://wiki.extremist.software/index.php?title=JavaScript/Notes/PrivateProxy&amp;diff=42493</id>
		<title>JavaScript/Notes/PrivateProxy</title>
		<link rel="alternate" type="text/html" href="https://wiki.extremist.software/index.php?title=JavaScript/Notes/PrivateProxy&amp;diff=42493"/>
		<updated>2014-05-16T23:22:27Z</updated>

		<summary type="html">&lt;p&gt;209.10.200.2: /* Private Proxy */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Proxy == &lt;br /&gt;
A proxy is as an interface to something else.&lt;br /&gt;
&lt;br /&gt;
== Private Proxy == &lt;br /&gt;
The private proxy exposes a public interface object. This public interface object delegates some of its responsibility to a private instance.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Structural Pattern:&#039;&#039;&#039; The private and public instances are &amp;lt;dfn&amp;gt;tightly coupled&amp;lt;/dfn&amp;gt;. They can share data with each other within the function where they are defined, but not outside of there. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Usage:&#039;&#039;&#039; This pattern is useful when you have details and complexities that can be hidden. By exposing a very limited set of methods, the code allows caller less opportunity to modify and break the objects it produces. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var Program = function(A) {&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;use strict&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  var phaseListClassName = &amp;quot;program-phase-list&amp;quot;,&lt;br /&gt;
      phaseClassName = &amp;quot;program-phase&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  function Program(id, config) {&lt;br /&gt;
    var start = config.startDate,&lt;br /&gt;
        end = config.endDate;&lt;br /&gt;
    this.id = id;&lt;br /&gt;
    this.dateRange = new A.DateRange(start, end);&lt;br /&gt;
    this.phases = config.phases.slice();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  var programs = {},&lt;br /&gt;
      programProxies = {};&lt;br /&gt;
&lt;br /&gt;
  var phaseListElement = document.createElement(&amp;quot;ul&amp;quot;),&lt;br /&gt;
      phaseElement = document.createElement(&amp;quot;li&amp;quot;);&lt;br /&gt;
  phaseListElement.className = phaseListClassName;&lt;br /&gt;
  phaseElement.className = phaseClassName;&lt;br /&gt;
&lt;br /&gt;
  function ProgramProxy(id, config) {&lt;br /&gt;
    this.id = id;&lt;br /&gt;
    this.start = config.startDate;&lt;br /&gt;
    this.displayName = config.name;&lt;br /&gt;
    this.end = config.endDate;&lt;br /&gt;
    programs[id] = new Program(id, config);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  ProgramProxy.prototype = {&lt;br /&gt;
    setPhases: function(phases) {&lt;br /&gt;
      if(phases &amp;amp;&amp;amp; phases.slice) {&lt;br /&gt;
        programs[this.id].phases = phases.slice();&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    buildHTML: function() {&lt;br /&gt;
      var program = programs[this.id],&lt;br /&gt;
          html = &amp;quot;&amp;quot;;&lt;br /&gt;
      html += buildPhaseHTML(program);&lt;br /&gt;
      html += buildCampaignHTML(program);&lt;br /&gt;
      return html;&lt;br /&gt;
    }&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  var div = document.createElement(&amp;quot;div&amp;quot;);&lt;br /&gt;
  function buildPhaseHTML(program) {&lt;br /&gt;
    div.innerHTML = &amp;quot;&amp;quot;;&lt;br /&gt;
    var i, li,&lt;br /&gt;
        phases = program.phases,&lt;br /&gt;
        len = phases.length,&lt;br /&gt;
        phaseRationalValue,&lt;br /&gt;
        ul = phaseListElement.cloneNode(false);&lt;br /&gt;
    ul.id = &amp;quot;program-&amp;quot; + program.id;&lt;br /&gt;
    for(i = 0; i &amp;lt; len; i++) {&lt;br /&gt;
      li = phaseElement.cloneNode(false);&lt;br /&gt;
      li.id = &amp;quot;program-&amp;quot;&lt;br /&gt;
            + program.id &lt;br /&gt;
            + &amp;quot;-phase-&amp;quot;&lt;br /&gt;
            + phases[i].name  &lt;br /&gt;
            + &amp;quot;&amp;quot;;&lt;br /&gt;
      li.style.width = &lt;br /&gt;
        getPhaseWidth(phases[i], program.dateRange.duration);&lt;br /&gt;
      ul.appendChild(li);&lt;br /&gt;
    }&lt;br /&gt;
    div.appendChild(ul);&lt;br /&gt;
    return div.innerHTML;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  function buildCampaignHTML() {&lt;br /&gt;
    return&amp;quot;&amp;quot;;&lt;br /&gt;
  &amp;quot;&amp;lt;ul&amp;gt;&amp;quot;&lt;br /&gt;
    + &amp;quot;&amp;lt;li&amp;gt;fixme:\u00A0buildCampaignHTML&amp;quot;&lt;br /&gt;
    + &amp;quot;&amp;lt;/ul&amp;gt;&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function getPhaseWidth(phase, programDuration) {&lt;br /&gt;
    var phaseDateRange = new A.DateRange(&lt;br /&gt;
      phase.startDate, phase.endDate);&lt;br /&gt;
    var rationalValue = phaseDateRange.duration/programDuration;&lt;br /&gt;
    return (0|100 * rationalValue) + &amp;quot;%&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function getOrCreateProgram(config) {&lt;br /&gt;
    return programProxies[config.id] || &lt;br /&gt;
      (programProxies[config.id] = new ProgramProxy(config.id, config));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function removeProgram(id) {&lt;br /&gt;
    if(!programs[id]) {&lt;br /&gt;
      throw new ReferenceError(&amp;quot;Program: &amp;quot; &lt;br /&gt;
        + id&lt;br /&gt;
        + &amp;quot; does not exist.&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
    delete programs[id];&lt;br /&gt;
    delete programProxies[id];&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return {&lt;br /&gt;
    getOrCreate: getOrCreateProgram,&lt;br /&gt;
    remove: removeProgram&lt;br /&gt;
  };&lt;br /&gt;
}({&lt;br /&gt;
  DateRange: DateRange // defined elsewhere.&lt;br /&gt;
});&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
`Program.getOrCreate` returns a `ProgramProxy`.&lt;br /&gt;
&lt;br /&gt;
`ProgramProxy` has two methods, both of which delegate to `Program` instances. &lt;br /&gt;
&lt;br /&gt;
The body of buildHTML&lt;br /&gt;
&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
setPhases: function(phases) {&lt;br /&gt;
 if(phases &amp;amp;&amp;amp; phases.slice) {&lt;br /&gt;
    programs[id].phases = phases.slice();&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is possible because `ProgramProxy` and each `Program` have the same id. Each are stored in one of two objects, keyed by their id. See also: [http://sourcemaking.com/design_patterns/proxy Proxy Design Pattern].&lt;/div&gt;</summary>
		<author><name>209.10.200.2</name></author>
	</entry>
	<entry>
		<id>https://wiki.extremist.software/index.php?title=JavaScript/Notes/PrivateProxy&amp;diff=42472</id>
		<title>JavaScript/Notes/PrivateProxy</title>
		<link rel="alternate" type="text/html" href="https://wiki.extremist.software/index.php?title=JavaScript/Notes/PrivateProxy&amp;diff=42472"/>
		<updated>2014-05-16T21:00:27Z</updated>

		<summary type="html">&lt;p&gt;209.10.200.2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;source lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
var Program = function() {&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;use strict&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  var phaseListClassName = &amp;quot;program-phase-list&amp;quot;,&lt;br /&gt;
      phaseClassName = &amp;quot;program-phase&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  function Program(id, config) {&lt;br /&gt;
    var start = config.startDate,&lt;br /&gt;
        end = config.endDate;&lt;br /&gt;
    this.id = id;&lt;br /&gt;
    this.dateRange = new A.AcxDateRange(start, end);&lt;br /&gt;
    this.phases = config.phases.slice();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  var programs = {},&lt;br /&gt;
      programProxies = {};&lt;br /&gt;
&lt;br /&gt;
  var phaseListElement = document.createElement(&amp;quot;ul&amp;quot;),&lt;br /&gt;
      phaseElement = document.createElement(&amp;quot;li&amp;quot;);&lt;br /&gt;
  phaseListElement.className = phaseListClassName;&lt;br /&gt;
  phaseElement.className = phaseClassName;&lt;br /&gt;
&lt;br /&gt;
  function ProgramProxy(id, config) {&lt;br /&gt;
    this.id = id;&lt;br /&gt;
    this.start = config.startDate;&lt;br /&gt;
    this.displayName = config.name;&lt;br /&gt;
    this.end = config.endDate;&lt;br /&gt;
    programs[id] = new Program(id, config);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  ProgramProxy.prototype = {&lt;br /&gt;
    setPhases: function(phases) {&lt;br /&gt;
      if(phases &amp;amp;&amp;amp; phases.slice) {&lt;br /&gt;
        programs[id].phases = phases.slice();&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    buildHTML: function() {&lt;br /&gt;
      var program = programs[this.id],&lt;br /&gt;
          html = &amp;quot;&amp;quot;;&lt;br /&gt;
      html += buildPhaseHTML(program);&lt;br /&gt;
      html += buildCampaignHTML(program);&lt;br /&gt;
      return html;&lt;br /&gt;
    }&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  var div = document.createElement(&amp;quot;div&amp;quot;);&lt;br /&gt;
  function buildPhaseHTML(program) {&lt;br /&gt;
    div.innerHTML = &amp;quot;&amp;quot;;&lt;br /&gt;
    var i, li,&lt;br /&gt;
        phases = program.phases,&lt;br /&gt;
        len = phases.length,&lt;br /&gt;
        phaseRationalValue,&lt;br /&gt;
        ul = phaseListElement.cloneNode(false);&lt;br /&gt;
    ul.id = &amp;quot;program-&amp;quot; + program.id;&lt;br /&gt;
    for(i = 0; i &amp;lt; len; i++) {&lt;br /&gt;
      li = phaseElement.cloneNode(false);&lt;br /&gt;
      li.id = &amp;quot;program-&amp;quot;&lt;br /&gt;
            + program.id &lt;br /&gt;
            + &amp;quot;-phase-&amp;quot;&lt;br /&gt;
            + phases[i].name  &lt;br /&gt;
            + &amp;quot;&amp;quot;;&lt;br /&gt;
      li.style.width = &lt;br /&gt;
        getPhaseWidth(phases[i], program.dateRange.duration);&lt;br /&gt;
      ul.appendChild(li);&lt;br /&gt;
    }&lt;br /&gt;
    div.appendChild(ul);&lt;br /&gt;
    return div.innerHTML;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  function buildCampaignHTML() {&lt;br /&gt;
    return&amp;quot;&amp;quot;;&lt;br /&gt;
  &amp;quot;&amp;lt;ul&amp;gt;&amp;quot;&lt;br /&gt;
    + &amp;quot;&amp;lt;li&amp;gt;fixme:\u00A0buildCampaignHTML&amp;quot;&lt;br /&gt;
    + &amp;quot;&amp;lt;/ul&amp;gt;&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function getPhaseWidth(phase, programDuration) {&lt;br /&gt;
    var phaseDateRange = new A.AcxDateRange(&lt;br /&gt;
      phase.startDate, phase.endDate);&lt;br /&gt;
    var rationalValue = phaseDateRange.duration/programDuration;&lt;br /&gt;
    return (0|100 * rationalValue) + &amp;quot;%&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function getOrCreateProgram(config) {&lt;br /&gt;
    return programProxies[config.id] || &lt;br /&gt;
      (programProxies[config.id] = new ProgramProxy(config.id, config));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function removeProgram(id) {&lt;br /&gt;
    if(!programs[id]) {&lt;br /&gt;
      throw new ReferenceError(&amp;quot;Program: &amp;quot; &lt;br /&gt;
        + id&lt;br /&gt;
        + &amp;quot; does not exist.&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
    delete programs[id];&lt;br /&gt;
    delete programProxies[id];&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return {&lt;br /&gt;
    getOrCreate: getOrCreateProgram,&lt;br /&gt;
    remove: removeProgram&lt;br /&gt;
  };&lt;br /&gt;
}();&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>209.10.200.2</name></author>
	</entry>
	<entry>
		<id>https://wiki.extremist.software/index.php?title=JavaScript/Notes/PrivateProxy&amp;diff=42471</id>
		<title>JavaScript/Notes/PrivateProxy</title>
		<link rel="alternate" type="text/html" href="https://wiki.extremist.software/index.php?title=JavaScript/Notes/PrivateProxy&amp;diff=42471"/>
		<updated>2014-05-16T20:59:13Z</updated>

		<summary type="html">&lt;p&gt;209.10.200.2: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;var Program = function() {&lt;br /&gt;
&lt;br /&gt;
  &amp;quot;use strict&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  var phaseListClassName = &amp;quot;program-phase-list&amp;quot;,&lt;br /&gt;
      phaseClassName = &amp;quot;program-phase&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
  function Program(id, config) {&lt;br /&gt;
    var start = config.startDate,&lt;br /&gt;
        end = config.endDate;&lt;br /&gt;
    this.id = id;&lt;br /&gt;
    this.dateRange = new A.AcxDateRange(start, end);&lt;br /&gt;
    this.phases = config.phases.slice();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  var programs = {},&lt;br /&gt;
      programProxies = {};&lt;br /&gt;
&lt;br /&gt;
  var phaseListElement = document.createElement(&amp;quot;ul&amp;quot;),&lt;br /&gt;
      phaseElement = document.createElement(&amp;quot;li&amp;quot;);&lt;br /&gt;
  phaseListElement.className = phaseListClassName;&lt;br /&gt;
  phaseElement.className = phaseClassName;&lt;br /&gt;
&lt;br /&gt;
  function ProgramProxy(id, config) {&lt;br /&gt;
    this.id = id;&lt;br /&gt;
    this.start = config.startDate;&lt;br /&gt;
    this.displayName = config.name;&lt;br /&gt;
    this.end = config.endDate;&lt;br /&gt;
    programs[id] = new Program(id, config);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  ProgramProxy.prototype = {&lt;br /&gt;
    setPhases: function(phases) {&lt;br /&gt;
      if(phases &amp;amp;&amp;amp; phases.slice) {&lt;br /&gt;
        programs[id].phases = phases.slice();&lt;br /&gt;
      }&lt;br /&gt;
    },&lt;br /&gt;
&lt;br /&gt;
    buildHTML: function() {&lt;br /&gt;
      var program = programs[this.id],&lt;br /&gt;
          html = &amp;quot;&amp;quot;;&lt;br /&gt;
      html += buildPhaseHTML(program);&lt;br /&gt;
      html += buildCampaignHTML(program);&lt;br /&gt;
      return html;&lt;br /&gt;
    }&lt;br /&gt;
  };&lt;br /&gt;
&lt;br /&gt;
  var div = document.createElement(&amp;quot;div&amp;quot;);&lt;br /&gt;
  function buildPhaseHTML(program) {&lt;br /&gt;
    div.innerHTML = &amp;quot;&amp;quot;;&lt;br /&gt;
    var i, li,&lt;br /&gt;
        phases = program.phases,&lt;br /&gt;
        len = phases.length,&lt;br /&gt;
        phaseRationalValue,&lt;br /&gt;
        ul = phaseListElement.cloneNode(false);&lt;br /&gt;
    ul.id = &amp;quot;program-&amp;quot; + program.id;&lt;br /&gt;
    for(i = 0; i &amp;lt; len; i++) {&lt;br /&gt;
      li = phaseElement.cloneNode(false);&lt;br /&gt;
      li.id = &amp;quot;program-&amp;quot;&lt;br /&gt;
            + program.id &lt;br /&gt;
            + &amp;quot;-phase-&amp;quot;&lt;br /&gt;
            + phases[i].name  &lt;br /&gt;
            + &amp;quot;&amp;quot;;&lt;br /&gt;
      li.style.width = &lt;br /&gt;
        getPhaseWidth(phases[i], program.dateRange.duration);&lt;br /&gt;
      ul.appendChild(li);&lt;br /&gt;
    }&lt;br /&gt;
    div.appendChild(ul);&lt;br /&gt;
    return div.innerHTML;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
  function buildCampaignHTML() {&lt;br /&gt;
    return&amp;quot;&amp;quot;;&lt;br /&gt;
  &amp;quot;&amp;lt;ul&amp;gt;&amp;quot;&lt;br /&gt;
    + &amp;quot;&amp;lt;li&amp;gt;fixme:\u00A0buildCampaignHTML&amp;quot;&lt;br /&gt;
    + &amp;quot;&amp;lt;/ul&amp;gt;&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function getPhaseWidth(phase, programDuration) {&lt;br /&gt;
    var phaseDateRange = new A.AcxDateRange(&lt;br /&gt;
      phase.startDate, phase.endDate);&lt;br /&gt;
    var rationalValue = phaseDateRange.duration/programDuration;&lt;br /&gt;
    return (0|100 * rationalValue) + &amp;quot;%&amp;quot;;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function getOrCreateProgram(config) {&lt;br /&gt;
    return programProxies[config.id] || &lt;br /&gt;
      (programProxies[config.id] = new ProgramProxy(config.id, config));&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  function removeProgram(id) {&lt;br /&gt;
    if(!programs[id]) {&lt;br /&gt;
      throw new ReferenceError(&amp;quot;Program: &amp;quot; &lt;br /&gt;
        + id&lt;br /&gt;
        + &amp;quot; does not exist.&amp;quot; );&lt;br /&gt;
    }&lt;br /&gt;
    delete programs[id];&lt;br /&gt;
    delete programProxies[id];&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  return {&lt;br /&gt;
    getOrCreate: getOrCreateProgram,&lt;br /&gt;
    remove: removeProgram&lt;br /&gt;
  };&lt;br /&gt;
}();&lt;/div&gt;</summary>
		<author><name>209.10.200.2</name></author>
	</entry>
</feed>