Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

...

  • Loading branch information...
commit 403001f43afc7a2dd6d5c2b6ab41b899b7e8c5c2 1 parent 3a9d462
@worrydream authored
View
11 Examples/CookieExample.js
@@ -9,8 +9,15 @@
window.addEvent('domready', function () {
new Tangle(document.getElementById("cookieExample"), {
- initialize: function () { this.cookies = 4; },
- update: function () { this.calories = this.cookies * 50; },
+ initialize: function () {
+ this.cookies = 3;
+ this.caloriesPerCookie = 50;
+ this.caloriesPerDay = 2100;
+ },
+ update: function () {
+ this.calories = this.cookies * this.caloriesPerCookie;
+ this.dailyPercent = Math.round(100 * this.calories / this.caloriesPerDay);
+ }
});
});
View
2  Examples/FilterExample.js
@@ -83,7 +83,7 @@ window.addEvent('domready', function () {
},
});
- tangle.setValue("index", 2);
+ tangle.setValue("index", 2); // initialize both kf1 and kf2, etc.
});
View
118 Examples/ParkExample.js
@@ -10,68 +10,68 @@ window.addEvent('domready', function () {
new Tangle(document.getElementById("parkExample"), {
- initialize: function () {
- this.parkCount = 278;
- this.oldAdmission = 12;
- this.registeredVehicleCount = 28e6; // http://www.yesforstateparks.com/get-the-facts/fact-sheets/general-fact-sheet
- this.taxpayerCount = 13657632; // http://trac.syr.edu/tracirs/findings/aboutTP/states/California/counties/06000/06000main.html
- this.oldVisitorCount = 75e6; // http://parks.ca.gov/pages/712/files/budget%20fact%20sheet%20w-graphics%20-%2001-14-08.pdf
- this.oldBudget = 400e6; // this is not really correct, it ignores revenue, but I couldn't find any revenue data
- this.oldClosedParkCount = 150;
+ initialize: function () {
+ this.parkCount = 278;
+ this.oldAdmission = 12;
+ this.registeredVehicleCount = 28e6; // http://www.yesforstateparks.com/get-the-facts/fact-sheets/general-fact-sheet
+ this.taxpayerCount = 13657632; // http://trac.syr.edu/tracirs/findings/aboutTP/states/California/counties/06000/06000main.html
+ this.oldVisitorCount = 75e6; // http://parks.ca.gov/pages/712/files/budget%20fact%20sheet%20w-graphics%20-%2001-14-08.pdf
+ this.oldBudget = 400e6; // this is not really correct, it ignores revenue, but I couldn't find any revenue data
+ this.oldClosedParkCount = 150;
- this.percentOfAdmissionConvertedToRevenue = 0.1; // total BS, couldn't find real data, just trying to make the numbers work
- this.percentInStateVistors = 85;
- this.percentVehicleOwners = 95;
+ this.percentOfAdmissionConvertedToRevenue = 0.1; // total BS, couldn't find real data, just trying to make the numbers work
+ this.percentInStateVistors = 85;
+ this.percentVehicleOwners = 95;
- this.tax = 18;
- this.percentCompliance = 100;
- this.isTaxPerVehicle = true;
- this.newAdmission = 0;
- this.newAdmissionAppliesToEveryone = false;
- },
-
- update: function () {
- var taxCount = this.isTaxPerVehicle ? this.registeredVehicleCount : this.taxpayerCount;
- this.taxCollected = this.tax * this.percentCompliance/100 * taxCount;
-
- var fractionOfVisitorsEligibleForNewAdmission = this.newAdmissionAppliesToEveryone ? 1 :
- (this.percentInStateVistors/100 * (this.isTaxPerVehicle ? (this.percentVehicleOwners/100) : 1));
- var averageAdmission = this.oldAdmission + fractionOfVisitorsEligibleForNewAdmission * (this.newAdmission - this.oldAdmission);
+ this.tax = 18;
+ this.percentCompliance = 100;
+ this.isTaxPerVehicle = true;
+ this.newAdmission = 0;
+ this.newAdmissionAppliesToEveryone = false;
+ },
+
+ update: function () {
+ var taxCount = this.isTaxPerVehicle ? this.registeredVehicleCount : this.taxpayerCount;
+ this.taxCollected = this.tax * this.percentCompliance/100 * taxCount;
+
+ var fractionOfVisitorsEligibleForNewAdmission = this.newAdmissionAppliesToEveryone ? 1 :
+ (this.percentInStateVistors/100 * (this.isTaxPerVehicle ? (this.percentVehicleOwners/100) : 1));
+ var averageAdmission = this.oldAdmission + fractionOfVisitorsEligibleForNewAdmission * (this.newAdmission - this.oldAdmission);
- // fake demand curve
- this.newVisitorCount = this.oldVisitorCount * Math.max(0.2, 1 + 0.5*Math.atan(1 - averageAdmission/this.oldAdmission));
-
- var oldRevenue = this.oldVisitorCount * this.oldAdmission * this.percentOfAdmissionConvertedToRevenue;
- var newRevenue = this.newVisitorCount * averageAdmission * this.percentOfAdmissionConvertedToRevenue;
-
- this.deltaRevenue = newRevenue - oldRevenue;
- this.deltaBudget = this.taxCollected + this.deltaRevenue;
- this.deltaVisitorCount = this.newVisitorCount - this.oldVisitorCount;
- this.relativeVisitorCount = Math.abs(this.deltaVisitorCount / this.oldVisitorCount);
+ // fake demand curve
+ this.newVisitorCount = this.oldVisitorCount * Math.max(0.2, 1 + 0.5*Math.atan(1 - averageAdmission/this.oldAdmission));
+
+ var oldRevenue = this.oldVisitorCount * this.oldAdmission * this.percentOfAdmissionConvertedToRevenue;
+ var newRevenue = this.newVisitorCount * averageAdmission * this.percentOfAdmissionConvertedToRevenue;
+
+ this.deltaRevenue = newRevenue - oldRevenue;
+ this.deltaBudget = this.taxCollected + this.deltaRevenue;
+ this.deltaVisitorCount = this.newVisitorCount - this.oldVisitorCount;
+ this.relativeVisitorCount = Math.abs(this.deltaVisitorCount / this.oldVisitorCount);
- this.budget = this.oldBudget + this.deltaBudget;
-
- var maintainanceBudget = 600e6;
- var repairBudget = 750e6;
- var maxBudget = 1000e6;
-
- if (this.budget < maintainanceBudget) {
- this.scenarioIndex = 0;
- this.closedParkCount = this.oldClosedParkCount * (maintainanceBudget - this.budget) / (maintainanceBudget - this.oldBudget);
- this.closedParkCount = Math.round(this.closedParkCount);
- }
- else if (this.budget < repairBudget) {
- this.scenarioIndex = 1;
- }
- else if (this.budget < maxBudget) {
- this.scenarioIndex = 2;
- this.restorationTime = Math.round(10 - 9 * (this.budget - repairBudget) / (maxBudget - repairBudget));
- }
- else {
- this.scenarioIndex = 3;
- this.surplus = this.budget - maxBudget;
- }
- },
- });
+ this.budget = this.oldBudget + this.deltaBudget;
+
+ var maintainanceBudget = 600e6;
+ var repairBudget = 750e6;
+ var maxBudget = 1000e6;
+
+ if (this.budget < maintainanceBudget) {
+ this.scenarioIndex = 0;
+ this.closedParkCount = this.oldClosedParkCount * (maintainanceBudget - this.budget) / (maintainanceBudget - this.oldBudget);
+ this.closedParkCount = Math.round(this.closedParkCount);
+ }
+ else if (this.budget < repairBudget) {
+ this.scenarioIndex = 1;
+ }
+ else if (this.budget < maxBudget) {
+ this.scenarioIndex = 2;
+ this.restorationTime = Math.round(10 - 9 * (this.budget - repairBudget) / (maxBudget - repairBudget));
+ }
+ else {
+ this.scenarioIndex = 3;
+ this.surplus = this.budget - maxBudget;
+ }
+ },
+ });
});
View
1  TangleKit/TangleKit.css
@@ -29,6 +29,7 @@
/* TKAdjustableNumber */
.TKAdjustableNumber {
+ position:relative;
color: #46f;
border-bottom: 1px dashed #46f;
}
View
304 TangleKit/TangleKit.js
@@ -12,69 +12,69 @@
//----------------------------------------------------------
//
-// formats
+// TKIf
//
+// Shows the element if value is true (non-zero), hides if false.
+// Add the data-invert="1" attribute to hide if false instead.
-function formatValueWithPrecision (value,precision) {
- if (Math.abs(value) >= 100) { precision--; }
- if (Math.abs(value) >= 10) { precision--; }
- return "" + value.round(Math.max(precision,0));
-}
-
-Tangle.formats.p3 = function (value) {
- return formatValueWithPrecision(value,3);
+Tangle.classes.TKIf = {
+
+ initialize: function (element, tangle, variable) {
+ this.isInverted = !!element.getAttribute("invert");
+ },
+
+ update: function (element, value) {
+ if (this.isInverted) { value = !value; }
+ element.style.display = !value ? "none" : "inline"; // todo, block or inline?
+ }
};
-Tangle.formats.neg_p3 = function (value) {
- return formatValueWithPrecision(-value,3);
-};
-Tangle.formats.p2 = function (value) {
- return formatValueWithPrecision(value,2);
-};
+//----------------------------------------------------------
+//
+// TKSwitch
+//
+// Shows the element's nth child if value is n.
-Tangle.formats.e6 = function (value) {
- return "" + (value * 1e-6).round();
-};
+Tangle.classes.TKSwitch = {
-Tangle.formats.abs_e6 = function (value) {
- return "" + (Math.abs(value) * 1e-6).round();
+ update: function (element, value) {
+ element.getChildren().each( function (child, index) {
+ child.style.display = (index != value) ? "none" : "inline";
+ });
+ }
};
-Tangle.formats.freq = function (value) {
- if (value < 100) { return "" + value.round(1) + " Hz"; }
- if (value < 1000) { return "" + value.round(0) + " Hz"; }
- return "" + (value / 1000).round(2) + " KHz";
-};
-Tangle.formats.dollars = function (value) {
- return "$" + value.round(0);
-};
+//----------------------------------------------------------
+//
+// TKPlusMinus
+//
+// Shows the element's first child if value is positive or zero.
+// Shows the element's second child if value is negative.
-Tangle.formats.free = function (value) {
- return value ? ("$" + value.round(0)) : "free";
-};
+Tangle.classes.TKPlusMinus = {
-Tangle.formats.percent = function (value) {
- return "" + (100 * value).round(0) + "%";
+ update: function (element, value) {
+ Tangle.classes.TKSwitch.update(element, value < 0);
+ }
};
-
//----------------------------------------------------------
//
// TKToggle
//
-// click to toggle value between 0 and 1
+// Click to toggle value between 0 and 1.
Tangle.classes.TKToggle = {
initialize: function (element, tangle, variable) {
- element.addEvent("click", function (event) {
- var isActive = tangle.getValue(variable);
- tangle.setValue(variable, isActive ? 0 : 1);
- });
- }
+ element.addEvent("click", function (event) {
+ var isActive = tangle.getValue(variable);
+ tangle.setValue(variable, isActive ? 0 : 1);
+ });
+ }
};
@@ -82,7 +82,7 @@ Tangle.classes.TKToggle = {
//
// TKAdjustableNumber
//
-// drag a number to adjust
+// Drag a number to adjust.
var isAnyAdjustableNumberDragging = false; // hack for dragging one value over another one
@@ -92,7 +92,6 @@ Tangle.classes.TKAdjustableNumber = {
this.element = element;
this.tangle = tangle;
this.variable = variable;
- this.container = tangle.element;
this.min = (element.getAttribute("data-min") !== null) ? parseFloat(element.getAttribute("data-min")) : 1;
this.max = (element.getAttribute("data-max") !== null) ? parseFloat(element.getAttribute("data-max")) : 10;
@@ -104,164 +103,141 @@ Tangle.classes.TKAdjustableNumber = {
},
- // hover
+ // hover
initializeHover: function () {
- this.isHovering = false;
- this.element.addEvent("mouseenter", (function () { this.isHovering = true; this.updateRolloverEffects(); }).bind(this));
- this.element.addEvent("mouseleave", (function () { this.isHovering = false; this.updateRolloverEffects(); }).bind(this));
+ this.isHovering = false;
+ this.element.addEvent("mouseenter", (function () { this.isHovering = true; this.updateRolloverEffects(); }).bind(this));
+ this.element.addEvent("mouseleave", (function () { this.isHovering = false; this.updateRolloverEffects(); }).bind(this));
},
updateRolloverEffects: function () {
- this.updateStyle();
- this.updateCursor();
- this.updateHelp();
- },
-
- isActive: function () {
- return this.isDragging || (this.isHovering && !isAnyAdjustableNumberDragging);
- },
-
- updateStyle: function () {
- if (this.isDragging) { this.element.addClass("TKAdjustableNumberDown"); }
- else { this.element.removeClass("TKAdjustableNumberDown"); }
-
- if (!this.isDragging && this.isActive()) { this.element.addClass("TKAdjustableNumberHover"); }
- else { this.element.removeClass("TKAdjustableNumberHover"); }
- },
-
- updateCursor: function () {
- var body = document.getElement("body");
- if (this.isActive()) { body.addClass("TKCursorDragHorizontal"); }
- else { body.removeClass("TKCursorDragHorizontal"); }
- },
-
-
- // help
+ this.updateStyle();
+ this.updateCursor();
+ this.updateHelp();
+ },
+
+ isActive: function () {
+ return this.isDragging || (this.isHovering && !isAnyAdjustableNumberDragging);
+ },
+
+ updateStyle: function () {
+ if (this.isDragging) { this.element.addClass("TKAdjustableNumberDown"); }
+ else { this.element.removeClass("TKAdjustableNumberDown"); }
+
+ if (!this.isDragging && this.isActive()) { this.element.addClass("TKAdjustableNumberHover"); }
+ else { this.element.removeClass("TKAdjustableNumberHover"); }
+ },
+
+ updateCursor: function () {
+ var body = document.getElement("body");
+ if (this.isActive()) { body.addClass("TKCursorDragHorizontal"); }
+ else { body.removeClass("TKCursorDragHorizontal"); }
+ },
+
+
+ // help
initializeHelp: function () {
- this.helpElement = (new Element("div", { "class": "TKAdjustableNumberHelp" })).inject(this.container, "top");
- this.helpElement.setStyle("display", "none");
- this.helpElement.set("text", "drag");
+ this.helpElement = (new Element("div", { "class": "TKAdjustableNumberHelp" })).inject(this.element, "top");
+ this.helpElement.setStyle("display", "none");
+ this.helpElement.set("text", "drag");
},
updateHelp: function () {
- var position = this.element.getPosition(this.container);
- var size = this.element.getSize();
- position.y -= size.y - 4;
- position.x += Math.round(0.5 * (size.x - 20));
- this.helpElement.setPosition(position);
- this.helpElement.setStyle("display", (this.isHovering && !isAnyAdjustableNumberDragging) ? "block" : "none");
- },
-
-
- // drag
-
- initializeDrag: function () {
- this.isDragging = false;
- new BVTouchable(this.element, this);
- },
-
- touchDidGoDown: function (touches) {
- this.valueAtMouseDown = this.tangle.getValue(this.variable);
- this.isDragging = true;
- isAnyAdjustableNumberDragging = true;
- this.updateRolloverEffects();
- this.updateStyle();
- },
-
- touchDidMove: function (touches) {
- var value = this.valueAtMouseDown + touches.translation.x / 5 * this.step;
- value = ((value / this.step).round() * this.step).limit(this.min, this.max);
- this.tangle.setValue(this.variable, value);
- this.updateHelp();
- },
-
- touchDidGoUp: function (touches) {
- this.helpElement.setStyle("display", "none");
- this.isDragging = false;
- isAnyAdjustableNumberDragging = false;
- this.updateRolloverEffects();
- this.updateStyle();
- }
-};
-
+ var size = this.element.getSize();
+ var top = -size.y + 7;
+ var left = Math.round(0.5 * (size.x - 20));
+ var display = (this.isHovering && !isAnyAdjustableNumberDragging) ? "block" : "none";
+ this.helpElement.setStyles({ left:left, top:top, display:display });
+ },
-//----------------------------------------------------------
-//
-// TKIf
-//
-// hides the element if value is zero
-// add the invertIf class to hide if non-zero instead
-
-Tangle.classes.TKIf = {
-
- initialize: function (element, tangle, variable) {
- this.isInverted = !!element.getAttribute("invert");
+ // drag
+
+ initializeDrag: function () {
+ this.isDragging = false;
+ new BVTouchable(this.element, this);
},
- update: function (element, value) {
- if (this.isInverted) { value = !value; }
- element.style.display = !value ? "none" : "inline"; // todo
+ touchDidGoDown: function (touches) {
+ this.valueAtMouseDown = this.tangle.getValue(this.variable);
+ this.isDragging = true;
+ isAnyAdjustableNumberDragging = true;
+ this.updateRolloverEffects();
+ this.updateStyle();
+ },
+
+ touchDidMove: function (touches) {
+ var value = this.valueAtMouseDown + touches.translation.x / 5 * this.step;
+ value = ((value / this.step).round() * this.step).limit(this.min, this.max);
+ this.tangle.setValue(this.variable, value);
+ this.updateHelp();
+ },
+
+ touchDidGoUp: function (touches) {
+ this.helpElement.setStyle("display", "none");
+ this.isDragging = false;
+ isAnyAdjustableNumberDragging = false;
+ this.updateRolloverEffects();
+ this.updateStyle();
}
};
+
+
//----------------------------------------------------------
//
-// TKIfElse
+// formats
//
-// shows the element's first child if value is non-zero
-// shows the element's second child if value is zero
-Tangle.classes.TKIfElse = {
+function formatValueWithPrecision (value,precision) {
+ if (Math.abs(value) >= 100) { precision--; }
+ if (Math.abs(value) >= 10) { precision--; }
+ return "" + value.round(Math.max(precision,0));
+}
- initialize: function (element, tangle, variable) {
- this.isInverted = !!element.getAttribute("invert");
- },
-
- update: function (element, value) {
- if (this.isInverted) { value = !value; }
- var children = element.getChildren();
- children[0].style.display = !value ? "none" : "inline";
- children[1].style.display = value ? "none" : "inline";
- }
+Tangle.formats.p3 = function (value) {
+ return formatValueWithPrecision(value,3);
};
+Tangle.formats.neg_p3 = function (value) {
+ return formatValueWithPrecision(-value,3);
+};
-//----------------------------------------------------------
-//
-// TKPlusMinus
-//
-// shows the element's first child if value is positive or zero
-// shows the element's second child if value is negative
-
-Tangle.classes.TKPlusMinus = {
+Tangle.formats.p2 = function (value) {
+ return formatValueWithPrecision(value,2);
+};
- update: function (element, value) {
- Tangle.classes.TKIfElse.update(element, value >= 0);
- }
+Tangle.formats.e6 = function (value) {
+ return "" + (value * 1e-6).round();
};
+Tangle.formats.abs_e6 = function (value) {
+ return "" + (Math.abs(value) * 1e-6).round();
+};
-//----------------------------------------------------------
-//
-// TKSwitch
-//
-// shows the element's nth child if value is n
+Tangle.formats.freq = function (value) {
+ if (value < 100) { return "" + value.round(1) + " Hz"; }
+ if (value < 1000) { return "" + value.round(0) + " Hz"; }
+ return "" + (value / 1000).round(2) + " KHz";
+};
-Tangle.classes.TKSwitch = {
+Tangle.formats.dollars = function (value) {
+ return "$" + value.round(0);
+};
- update: function (element, value) {
- element.getChildren().each( function (child, index) {
- child.style.display = (index !== value) ? "none" : "inline";
- });
- }
+Tangle.formats.free = function (value) {
+ return value ? ("$" + value.round(0)) : "free";
};
+Tangle.formats.percent = function (value) {
+ return "" + (100 * value).round(0) + "%";
+};
+
//----------------------------------------------------------
})();
View
21 download.html
@@ -24,9 +24,10 @@
<h3>explorable explanations made easy</h3>
<div class="menu">
- <a class="menuGuide" href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
- <a class="menuReference" href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
- <a class="menuDownload" href="download.html">Download</a>
+ <a href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
+ <a href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
+ <a href="download.html">Download</a> &nbsp; &nbsp; &nbsp;
+ <a href="https://groups.google.com/group/tangle-talk">Discuss</a>
</div>
</div> <!-- header -->
@@ -42,7 +43,9 @@
<p><b><a href="Downloads/Tangle-0.1.0.zip">Tangle-0.1.0.zip</a></b> &mdash; released June 14, 2011</p>
-<p>Or visit the project on <a href="https://github.com/worrydream/Tangle">GitHub</a>.</p>
+<p>Visit the project on <a href="https://github.com/worrydream/Tangle">GitHub</a>.</p>
+
+<p>Join the brand new <a href="https://groups.google.com/group/tangle-talk">Tangle Talk</a> discussion group!</p>
<h2>What's In The Box</h2>
@@ -55,11 +58,12 @@
<h2>How You Can Help</h2>
-<p>This is an <b>alpha</b> release. That means that the API is subject to change, and such changes may break your code. TangleKit is currently a bit of a hodge-podge, and almost certainly will change.</p>
+<p>This is an <b>alpha</b> release. That means that the API is subject to change, and such changes may break your code. TangleKit is currently a hodge-podge, and almost certainly will change.</p>
<p>But don't let that stop you. <b>Make things with Tangle!</b> Here's how you can help:</p>
<ul style="margin-left:20px; list-style-type:disc;">
+<li>Join the <a href="https://groups.google.com/group/tangle-talk">Tangle Talk</a> discussion group.</li>
<li>Let us know if the API makes it difficult to do something you want to do.</li>
<li>Contribute Tangle classes and formats for possible inclusion with TangleKit.</li>
<li>Contribute documents you've made for possible inclusion in the examples.</li>
@@ -82,9 +86,10 @@
<div class="author">by <a href="http://worrydream.com/">Bret Victor</a></div>
<div class="menu">
- <a class="menuGuide" href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
- <a class="menuReference" href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
- <a class="menuDownload" href="download.html">Download</a>
+ <a href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
+ <a href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
+ <a href="download.html">Download</a> &nbsp; &nbsp; &nbsp;
+ <a href="https://groups.google.com/group/tangle-talk">Discuss</a>
</div>
</div> <!-- footer -->
View
111 guide.html
@@ -9,6 +9,19 @@
<link rel="stylesheet" href="Fonts/BorisBlackBloxx/stylesheet.css" type="text/css">
<link rel="stylesheet" href="style.css" type="text/css">
+ <!-- Tangle -->
+ <script type="text/javascript" src="Tangle.js"></script>
+
+ <!-- TangleKit -->
+ <link rel="stylesheet" href="TangleKit/TangleKit.css" type="text/css">
+ <script type="text/javascript" src="TangleKit/mootools.js"></script>
+ <script type="text/javascript" src="TangleKit/sprintf.js"></script>
+ <script type="text/javascript" src="TangleKit/BVTouchable.js"></script>
+ <script type="text/javascript" src="TangleKit/TangleKit.js"></script>
+
+ <!-- examples -->
+ <script type="text/javascript" src="Examples/CookieExample.js"></script>
+
</head>
<body>
@@ -24,9 +37,10 @@
<h3>explorable explanations made easy</h3>
<div class="menu">
- <a class="menuGuide" href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
- <a class="menuReference" href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
- <a class="menuDownload" href="download.html">Download</a>
+ <a href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
+ <a href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
+ <a href="download.html">Download</a> &nbsp; &nbsp; &nbsp;
+ <a href="https://groups.google.com/group/tangle-talk">Discuss</a>
</div>
</div> <!-- header -->
@@ -40,6 +54,90 @@
<h2>Getting Started</h2>
+<p>Tangle lets you write documents that change.</p>
+
+<p>Let's say you're writing an article about dieting, and want to discuss the calorie content of various foods. You might write the following sentences.</p>
+
+<div class="example">
+ <div class="exampleTop"></div>
+ <div class="exampleCenter">
+ <p>When you eat 3 cookies, you consume <b>150 calories</b>. That's 7% of your recommended daily calories.</p>
+ </div>
+ <div class="exampleBottom"></div>
+</div>
+
+<p>That's a true statement, but it only applies directly to those few readers who eat 3 cookies a day. Most of your readers eat more or less. What if the reader could adjust the statement to see information about their own situation? What if readers could explore alternative scenarios as well?</p>
+
+<div id="cookieExample" class="example">
+ <div class="exampleTop"></div>
+ <div class="exampleCenter">
+ <p>When you eat <span data-var="cookies" class="TKAdjustableNumber" data-min="2" data-max="100"> cookies</span>, you consume <b data-var="calories"></b> calories. That's <span data-var="dailyPercent">%</span> of your recommended daily calories.</p>
+ </div>
+ <div class="exampleBottom"></div>
+</div>
+
+<p>How do we make this?</p>
+
+
+<h2>Variables</h2>
+
+<p>We start by identifying the <strong>variables</strong> &mdash; those parts of the statement that need to change. In this case, there are three varying numbers in the statement, so we need three variables.</p>
+
+<div class="example">
+ <div class="exampleTop"></div>
+ <div class="exampleCenter">
+ <p>When you eat <strong>3 cookies</strong>, you consume <strong>150 calories</strong>. That's <strong>7%</strong> of your recommended daily calories.</p>
+ </div>
+ <div class="exampleBottom"></div>
+</div>
+
+<p>We'll call these variables <strong>cookies</strong>, <strong>calories</strong>, and <strong>dailyPercent</strong> respectively.</p>
+
+
+<h2>HTML</h2>
+
+<p>Now, let's look at the HTML for the statement.</p>
+
+<p><code><pre>
+&lt;p&gt;When you eat 3 cookies, you consume &lt;b&gt;150 calories&lt;/b&gt;.
+ That's 7% of your recommended daily calories.&lt;/p&gt;
+</pre></code></p>
+
+<p>Let's start with the "150 calories" part. Notice that it's inside <code>&lt;b&gt;</code> tags, to make it bold. We'll make two simple changes:</p>
+
+<p><code><pre>
+&lt;p&gt;When you eat 3 cookies, you consume &lt;b <strong>data-var="calories"</strong>&gt; calories&lt;/b&gt;.
+ That's 7% of your recommended daily calories.&lt;/p&gt;
+</pre></code></p>
+
+<p>First, we added the <code>data-var="calories"</code> attribute to the &lt;b&gt; tag. This tells Tangle to insert the value of the "calories" variable inside the tag. So, if the calories variable were 500, it would appear as "500 calories".</p>
+
+<p>Second, we removed the "150" from inside the tag, because Tangle is going to insert the correct number itself.</p>
+
+<p>Now, let's look at the "7%" part. It's not inside a tag, so we need to put it inside one. The <code>&lt;span&gt;</code> tag is typically used for this purpose. Unlike <code>&lt;b&gt;</code>, it has no intrinsic meaning of its own &mdash; it's simply a generic container that we can attach style and variable information to.</p>
+
+<p><code><pre>
+&lt;p&gt;When you eat 3 cookies, you consume &lt;b data-var="calories"&gt; calories&lt;/b&gt;.
+ That's <strong>&lt;span data-var="dailyPercent"&gt;</strong>%<strong>&lt;/span&gt;</strong> of your recommended daily calories.&lt;/p&gt;
+</pre></code></p>
+
+<p>Tangle will insert the value of the "dailyPercent" variable at the start of the span.</p>
+
+<p>Finally, we'll look at the "3 cookies" part. This part isn't just dynamic &mdash; it's interactive. We want the reader to be able to adjust the variable by dragging on the number. For this, we use a "class". A Tangle class can describe how the reader interacts with an HTML element, or how a variable should be displayed.</p>
+
+<p>We'll use the class "<code>TKAdjustableNumber</code>", which comes with TangleKit. (The "TK" prefix refers to "TangleKit".) TangleKit is a collection of basic classes for you to use. Once you start tangling more heavily, you might want to start making your own classes.</p>
+
+<p><code><pre>
+&lt;p&gt;When you eat <strong>&lt;span class="TKAdjustableNumber" data-var="cookies"&gt;</strong> cookies<strong>&lt;/span&gt;</strong>,
+ you consume &lt;b data-var="calories"&gt; calories&lt;/b&gt;. That's
+ &lt;span data-var="dailyPercent"&gt;%&lt;/span&gt; of your recommended daily calories.&lt;/p&gt;
+</pre></code></p>
+
+<p>That's all we need to do with the HTML. Next, we'll tell Tangle how to calculate those variables.</p>
+
+
+<h2>JavaScript</h2>
+
</div> <!-- body -->
@@ -54,9 +152,10 @@
<div class="author">by <a href="http://worrydream.com/">Bret Victor</a></div>
<div class="menu">
- <a class="menuGuide" href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
- <a class="menuReference" href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
- <a class="menuDownload" href="download.html">Download</a>
+ <a href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
+ <a href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
+ <a href="download.html">Download</a> &nbsp; &nbsp; &nbsp;
+ <a href="https://groups.google.com/group/tangle-talk">Discuss</a>
</div>
</div> <!-- footer -->
View
18 index.html
@@ -41,9 +41,10 @@
<h3>explorable explanations made easy</h3>
<div class="menu">
- <a class="menuGuide" href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
- <a class="menuReference" href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
- <a class="menuDownload" href="download.html">Download</a>
+ <a href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
+ <a href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
+ <a href="download.html">Download</a> &nbsp; &nbsp; &nbsp;
+ <a href="https://groups.google.com/group/tangle-talk">Discuss</a>
</div>
</div> <!-- header -->
@@ -124,9 +125,9 @@
<p>Suppose that an extra
<span data-var="tax" data-format="$%d" class="TKAdjustableNumber" data-min="0" data-max="50"></span> was charged to
<span data-var="percentCompliance" class="TKAdjustableNumber" data-min="0" data-max="100" data-step="5">%</span> of
- <span data-var="isTaxPerVehicle" class="TKToggle TKIfElse"><span>vehicle registrations</span><span>California taxpayers</span></span>.
+ <span data-var="isTaxPerVehicle" class="TKToggle TKSwitch"><span>California taxpayers</span><span>vehicle registrations</span></span>.
Park admission would be <span data-var="newAdmission" data-format="free" class="TKAdjustableNumber" data-min="0" data-max="25"></span> for
- <span data-var="newAdmissionAppliesToEveryone" class="TKToggle TKIfElse"><span>everyone</span><span>those who paid the charge</span></span>.
+ <span data-var="newAdmissionAppliesToEveryone" class="TKToggle TKSwitch"><span>those who paid the charge</span><span>everyone</span></span>.
</p>
<p>This would <span data-var="deltaBudget" class="TKPlusMinus"><span>collect an extra</span><span>lose</span></span>
@@ -260,9 +261,10 @@
<div class="author">by <a href="http://worrydream.com/">Bret Victor</a></div>
<div class="menu">
- <a class="menuGuide" href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
- <a class="menuReference" href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
- <a class="menuDownload" href="download.html">Download</a>
+ <a href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
+ <a href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
+ <a href="download.html">Download</a> &nbsp; &nbsp; &nbsp;
+ <a href="https://groups.google.com/group/tangle-talk">Discuss</a>
</div>
</div> <!-- footer -->
View
43 reference.html
@@ -3,8 +3,8 @@
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<base target="_top">
-
<title>Tangle: API Reference</title>
+
<link href='http://fonts.googleapis.com/css?family=Lato' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="Fonts/BorisBlackBloxx/stylesheet.css" type="text/css">
<link rel="stylesheet" href="style.css" type="text/css">
@@ -24,9 +24,10 @@
<h3>explorable explanations made easy</h3>
<div class="menu">
- <a class="menuGuide" href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
- <a class="menuReference" href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
- <a class="menuDownload" href="download.html">Download</a>
+ <a href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
+ <a href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
+ <a href="download.html">Download</a> &nbsp; &nbsp; &nbsp;
+ <a href="https://groups.google.com/group/tangle-talk">Discuss</a>
</div>
</div> <!-- header -->
@@ -44,9 +45,12 @@
<li><a href="#api">JavaScript API</a></li>
<li><a href="#classes">Tangle.classes</a></li>
<li><a href="#formats">Tangle.formats</a></li>
+<li><a href="#kit">TangleKit</a></li>
</ul>
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<!-- HTML attributes -->
<h2 id="html">HTML attributes</h2>
@@ -67,7 +71,7 @@ <h4 id="class">class</h4>
<p>See <a href="#classes">Tangle.classes</a> for details on how to write and plug in a class.</p>
-<p>An element can have any number of classes, like so:&nbsp; <code>&lt;span <b>class="MyClass MyOtherClass" data-var="cookies"&gt;</b></code>.&nbsp; Any of the classes can be defined in CSS, JavaScript, both, or neither.</p>
+<p>An element can have any number of classes, like so:&nbsp; <code>&lt;span <b>class="MyClass MyOtherClass" data-var="cookies"&gt;</b></code>.&nbsp; Any of the classes can be defined in CSS, JavaScript, both, or neither. You might use one class for the visual presentation of a variable, and another to provide interactive manipulation.</p>
<h4 id="data-var">data-var</h4>
@@ -108,6 +112,9 @@ <h4 id="data-other">other data attributes</h4>
<p>For details, see the documentation for the individual class.</p>
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<!-- JavaScript API -->
+
<p style="text-align:center; margin-top:40px;">*&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;*</p>
<h2 id="api">JavaScript API</h2>
@@ -206,6 +213,8 @@ <h4 id="setValues">setValues</h4>
<p>Sets values for multiple variables at once.</p>
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<!-- Tangle.classes -->
<p style="text-align:center; margin-top:40px;">*&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;*</p>
@@ -290,7 +299,7 @@ <h2 id="classes">Tangle.classes</h2>
<h6>framework classes</h6>
-<p>If <code>Tangle.classes.MyClass</code> is a function instead of an object, Tangle will call it as a constructor, instead of directly invoking an <code>initialize</code> method. This allows you to use classes from MooTools or some other framework, and take advantage of inheritance and other features.</p>
+<p>If <code>Tangle.classes.MyClass</code> is a function instead of an object, Tangle will call it as a constructor, instead of directly invoking an <code>initialize</code> method. So, if you're using a framework such as MooTools that has its own notion of what a "class" is, you can use its classes directly, and take advantage of inheritance and other features.</p>
<p><code><pre>
Tangle.classes.MyClass = new Class({ // assuming we're using MooTools
@@ -323,6 +332,9 @@ <h2 id="classes">Tangle.classes</h2>
<p>This is useful for two-dimensional controls that adjust two variables at once, or views that display multiple variables.</p>
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<!-- Tangle.formats -->
+
<p style="text-align:center; margin-top:40px;">*&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;*</p>
<h2 id="formats">Tangle.formats</h2>
@@ -348,6 +360,18 @@ <h2 id="formats">Tangle.formats</h2>
<p>You can often use printf-style formats instead, but <code>Tangle.formats</code> is available for your custom formatting needs. To use printf-style formats, you must include a sprintf library, such as the one that is provided with TangleKit.</p>
+<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
+<!-- TangleKit -->
+
+<p style="text-align:center; margin-top:40px;">*&nbsp;&nbsp;&nbsp;*&nbsp;&nbsp;&nbsp;*</p>
+
+<h2 id="kit">TangleKit</h2>
+
+<p>TangleKit is an optional collection of Tangle classes and formats, for adjusting variables and visualizing values. You can grab whichever components you want, use them, extend them, modify them, or just learn from them and make your own.</p>
+
+<p>TangleKit is currently pretty rudimentary, and not yet documented here. You can look through <a href="TangleKit/TangleKit.js">TangleKit.js</a> for what's currently available.</p>
+
+
</div> <!-- body -->
@@ -360,9 +384,10 @@ <h2 id="formats">Tangle.formats</h2>
<div class="author">by <a href="http://worrydream.com/">Bret Victor</a></div>
<div class="menu">
- <a class="menuGuide" href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
- <a class="menuReference" href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
- <a class="menuDownload" href="download.html">Download</a>
+ <a href="guide.html">Getting Started</a> &nbsp; &nbsp; &nbsp;
+ <a href="reference.html">API Reference</a> &nbsp; &nbsp; &nbsp;
+ <a href="download.html">Download</a> &nbsp; &nbsp; &nbsp;
+ <a href="https://groups.google.com/group/tangle-talk">Discuss</a>
</div>
</div> <!-- footer -->
View
13 style.css
@@ -1,5 +1,9 @@
* { margin: 0; padding: 0; }
+html {
+ overflow-y: scroll;
+}
+
body {
background: #eee0c7;
font: 14px "Lato", "Helvetica", "Arial", sans-serif;
@@ -62,7 +66,7 @@ body {
#header .menu {
position: absolute;
- left: 400px;
+ left: 320px;
top: 50px;
}
@@ -101,7 +105,7 @@ body {
#footer .menu {
position: absolute;
- left: 400px;
+ left: 320px;
top: 12px;
}
@@ -212,6 +216,11 @@ h6 {
margin-bottom:-5px;
}
+strong {
+ font-weight: bold;
+ color: #e00;
+}
+
.small pre {
background-color:rgba(255,255,255,0.18);
padding-left:12px;
View
12 template.html
@@ -7,7 +7,7 @@
<!-- Tangle -->
<script type="text/javascript" src="Tangle.js"></script>
- <!-- TangleKit -->
+ <!-- TangleKit (optional) -->
<link rel="stylesheet" href="TangleKit/TangleKit.css" type="text/css">
<script type="text/javascript" src="TangleKit/mootools.js"></script>
<script type="text/javascript" src="TangleKit/sprintf.js"></script>
@@ -17,27 +17,25 @@
<!-- example -->
<script type="text/javascript">
- function setUpExample () {
+ function setUpTangle () {
var element = document.getElementById("example");
var tangle = new Tangle(element, {
-
initialize: function () {
this.cookies = 4;
+ this.caloriesPerCookie = 50;
},
-
update: function () {
- this.calories = this.cookies * 50;
+ this.calories = this.cookies * this.caloriesPerCookie;
}
-
});
}
</script>
</head>
-<body onload="setUpExample();">
+<body onload="setUpTangle();">
<p>This is a simple reactive document.</p>
Please sign in to comment.
Something went wrong with that request. Please try again.