PageSourceSearch

https://thoppe.github.io/artisanal-boxes.js/artisanal-boxes.js

js thoppe.github.io collected 2026-10-03 10:04:57 UTC 6,003 bytes, 236 lines download raw bytes

1var eq = {
2    A:null,
3    b:null,
4    N:null,
5    sol:null,
6    eqn_idx:null
7};
8function solve_all_artboxes(suppress_ready) {
9    $(".artbox").each(solve_artbox);
10
11    // Fire off an event when the artbox is solved for other libaries
12    if(suppress_ready != true) {
13        $(".artbox").each(function() {
14            $(this).trigger("ready");
15        });
16    };
17
18};
19
20$(document).ready(function() {
21    solve_all_artboxes(suppress_ready=true);
22}); 
23
24$(window).on("load", function() { 
25    solve_all_artboxes();
26});
27
28$(window).resize( solve_all_artboxes );
29
30
31function solve_artbox() {
32
33    // Remove any previous set widths or heights
34    $(this).css({"height":"","width":""});
35
36    // Label the selectors
37    var nodes  = $(".node", this);
38    var boxes  = $(".hbox, .vbox", this)
39    var all_items = $(".node, .vbox, .hbox", this);
40
41    // Assign a matrix index to each item
42    all_items.each(index_items);
43
44    // Loop through all the nodes and measure the aspect
45    nodes.each(measure_aspect);
46
47    // Reserve space for the matrix equations
48    eq.N = 2*all_items.length;
49    eq.A = numeric.rep([eq.N,eq.N],0);
50    eq.b = numeric.rep([eq.N],0);
51    eq.eqn_idx = 0;
52
53    // Loop over the nodes, assign matrix equations
54    nodes.each(assign_node_equation);
55
56    // Loop over the boxes, assign matrix equations
57    boxes.each(assign_box_equations);
58
59    // Set the final width (for now, no final height)
60    set_final_width(this);
61    
62    // Solve the matrix equations
63    eq.sol = numeric.solve(eq.A,eq.b);
64
65    // Scale all the nodes
66    nodes.each(scale_nodes_to_size);
67
68    // Set the dimensions for the boxes
69    // Using the updated width/height now set the boxes aspect
70    boxes.each(set_dimensions);
71
72    // Set the first box to (0,0) position
73    boxes.first().css({left:0,top:0});
74    boxes.each(set_positions);
75
76    // Set the width, height on the artbox so other elements can
77    // flow around it properly
78    $(this).css({"height":get_y_sol(0),
79                 "width" :get_x_sol(0)});
80
81    // DEBUG: output
82    //all_items.each(function() {console.log($(this).data())});
83};
84
85
86function print(a) { console.log(numeric.prettyPrint(a)); };
87
88/* *********************************************************** */
89function scale_nodes_to_size() {
90    var idx   = $(this).data("index");
91    var scale = get_x_sol(idx)/measure_width(this);
92    transform_scale($(this), scale);
93};
94
95/* *********************************************************** */
96function set_positions() {
97    var kids  = $(this).children(".node, .vbox, .hbox");
98    var delta = 0;
99
100    if ($(this).hasClass("vbox")) {
101	      kids.each(function() { 
102	          $(this).css({left:0,top:delta});
103	          delta += get_y_sol($(this).data("index"));
104	      });
105    }
106
107    else if ($(this).hasClass("hbox")) {
108	      kids.each(function() { 
109	          $(this).css({left:delta,top:0});
110	          delta += get_x_sol( $(this).data("index") );
111	      });
112    };
113};
114
115/* *********************************************************** */
116
117function set_dimensions() {
118    var idx = $(this).data("index");
119    $(this).width ( get_x_sol(idx) );
120    $(this).height( get_y_sol(idx) );
121};
122
123/* *********************************************************** */
124// Helper functions
125/* *********************************************************** */
126
127function set_x_equation(idx, val) {
128    eq.A[eq.eqn_idx][idx] = val;
129}
130function set_y_equation(idx, val) {
131    eq.A[eq.eqn_idx][eq.N/2+idx] = val;
132};
133
134function get_y_sol(idx) {
135    return eq.sol[eq.N/2+idx];
136};
137
138function get_x_sol(idx) {
139    return eq.sol[idx];
140};
141
142/* *********************************************************** */
143function set_final_width(ele) {
144    set_x_equation(0,1);
145    eq.b[eq.eqn_idx] = measure_width(ele);
146    eq.eqn_idx += 1;
147};
148
149function set_final_height(ele) {
150    set_y_equation(0,1);
151    eq.b[eq.eqn_idx] = measure_height(ele);
152    eq.eqn_idx += 1;
153};
154
155/* *********************************************************** */
156function assign_box_equations() {
157
158    // Determine if we are vertical or horzontial
159    var f1, f2;
160    if($(this).hasClass("vbox")) {
161	      f1 = set_y_equation;
162	      f2 = set_x_equation;
163    }
164    else if($(this).hasClass("hbox")) {
165	      f1 = set_x_equation;
166	      f2 = set_y_equation;
167    };
168
169    var self_idx = $(this).data("index");
170    var kids     = $(this).children(".node, .vbox, .hbox");
171
172    // Sum along growth direction equals parent
173    kids.each(function() {
174	      var kid_idx = $(this).data("index");
175	      f1(kid_idx, 1);
176    });
177
178    f1(self_idx, -1);
179    eq.eqn_idx += 1;
180
181    // Each of the childrens dimension must match the parent
182    kids.each(function() {
183	      var kid_idx = $(this).data("index");
184	      f2(kid_idx ,  1);
185	      f2(self_idx, -1);
186	      eq.eqn_idx += 1;
187    });
188};
189
190function assign_node_equation() {
191    // Set constraint [(width)/(height) = aspect ratio]
192    var idx = $(this).data("index");
193    var aspect = $(this).data("aspect");
194    set_x_equation(idx,1);
195    set_y_equation(idx,-aspect);
196    eq.eqn_idx += 1;
197};
198
199/* *********************************************************** */
200
201function index_items(idx,ele) {
202    $(this).data("index",idx);
203};
204
205function measure_width(ele) {
206    // Measures the width to subpixel precision, jQuery rounds
207    return parseFloat(window.getComputedStyle(ele).width);
208}
209
210function measure_height(ele) {
211    return parseFloat(window.getComputedStyle(ele).height);
212}
213
214function measure_aspect() {
215    var aspect = measure_width(this)/measure_height(this);
216    $(this).data("aspect",aspect);   
217};
218
219/* Cross browser CSS3 functions */                 
220
221function transform_origin(ele, x_pct, y_pct) {
222    var coords = x_pct + "% " + y_pct + "%";
223    ele.css("transform-origin",coords);
224    ele.css("-ms-transform-origin",coords);
225    ele.css("-o-transform-origin",coords);
226}
227
228function transform_scale(ele, scale) {
229    var coords = 'scale('+scale+')';
230    ele.css({"transform":coords});
231    ele.css({"-ms-transform":coords});
232    ele.css({"-o-transform":coords});
233}
234
235
236

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.