rev |
line source |
pascal@15573
|
1 <?php # coding: utf-8
|
pascal@15573
|
2
|
pascal@15573
|
3 class Calc
|
pascal@15573
|
4 {
|
pascal@15573
|
5 public $description = "Feuille de calcul au format CSV";
|
pascal@15573
|
6
|
pascal@15573
|
7 var $lines = 0, $rows = 0, $cnt = 0, $gotcalc = 0, $line = array();
|
pascal@15573
|
8 var $newCONTENT;
|
pascal@15573
|
9 function showcalc()
|
pascal@15573
|
10 {
|
pascal@15573
|
11 if ($this->lines > 1 && $this->rows > 1) {
|
pascal@15573
|
12 $id = "C".(100+$this->cnt++);
|
pascal@15573
|
13 $this->newCONTENT .= "<noscript><a href=\"http://www.enable-javascript.com/\" target=\"_blank\">Enable javascript to see the spreadsheet ".$id."</a></noscript>\n";
|
pascal@15573
|
14 $this->newCONTENT .= "<table id=\"".$id."\" class=\"tablecalc\"></table>\n";
|
pascal@15573
|
15 $this->newCONTENT .= "<script type=\"text/javascript\">\n";
|
pascal@15573
|
16 $this->newCONTENT .= "<!--\n";
|
pascal@15573
|
17 $this->newCONTENT .= "buildCalc(\"".$id."\",".$this->lines.",".$this->rows.");\n";
|
pascal@15573
|
18 for ($i = 1; $i <= $this->lines; $i++) {
|
pascal@15573
|
19 $this->line[$i] = preg_replace("/</","<",$this->line[$i]);
|
pascal@15573
|
20 for ($tmp = explode(";",$this->line[$i]), $j = 0; $j < count($tmp) -1; $j++) {
|
pascal@15573
|
21 if ($tmp[$j] == "") continue;
|
pascal@15573
|
22 $tmp[$j] = preg_replace("/\"/","\\\\\"",$tmp[$j]);
|
pascal@15573
|
23 $s = "setCell(document.getElementById(\"".$id;
|
pascal@15573
|
24 $this->newCONTENT .= $s.chr(ord('A')+$j).$i."\"), \"".$tmp[$j]."\")\n";
|
pascal@15573
|
25 }
|
pascal@15573
|
26 }
|
pascal@15573
|
27 $this->newCONTENT .= "//-->\n";
|
pascal@15573
|
28 $this->newCONTENT .= "</script>\n";
|
pascal@15573
|
29 }
|
pascal@15573
|
30 else for ($i = 1; $i <= $this->lines; $i++)
|
pascal@15573
|
31 $this->newCONTENT .= $this->line[$i]."\n";
|
pascal@15573
|
32 $this->rows = $this->lines = $this->gotcalc = 0;
|
pascal@15573
|
33 }
|
pascal@15573
|
34
|
pascal@15573
|
35 function formatEnd()
|
pascal@15573
|
36 {
|
pascal@15573
|
37 global $CONTENT;
|
pascal@15573
|
38 $headdone = $gotcalc = $showtail = $this->lines = 0;
|
pascal@15573
|
39 $this->newCONTENT = "";
|
pascal@15573
|
40 $CONTENT = preg_replace("/<br \/>/","<br />\n",$CONTENT);
|
pascal@15573
|
41 foreach (explode("\n", $CONTENT) as $current) {
|
pascal@15573
|
42 if ($current == "") continue;
|
pascal@15573
|
43 if (preg_match("/;<br \/>$/", $current)) {
|
pascal@15573
|
44 $gotcalc = 1;
|
pascal@15573
|
45 if (!$headdone) {
|
pascal@15573
|
46 $headdone = 1;
|
pascal@15573
|
47 $showtail = 1;
|
pascal@15573
|
48 $this->newCONTENT .= <<<EOT
|
pascal@15573
|
49 <!-- Based on http://jsfiddle.net/ondras/hYfN3/ by Ondřej Žára -->
|
pascal@15573
|
50 <script type="text/javascript">
|
pascal@15573
|
51 <!--
|
pascal@15573
|
52 function csv(id,rows,cols) {
|
pascal@15573
|
53 var data = "";
|
pascal@15573
|
54 for (var i=1; i<=rows; i++) {
|
pascal@15573
|
55 for (var j=1; j<=cols; j++) {
|
pascal@15573
|
56 var letter = String.fromCharCode("A".charCodeAt(0)+j-1);
|
pascal@15573
|
57 data += document.getElementById(id+letter+i).title+';';
|
pascal@15573
|
58 }
|
pascal@15573
|
59 data += "\\n";
|
pascal@15573
|
60 }
|
pascal@15573
|
61 alert(data);
|
pascal@15573
|
62 }
|
pascal@15573
|
63
|
pascal@17794
|
64 function cnt(from,to) {
|
pascal@17794
|
65 return (to.charCodeAt(0) - from.charCodeAt(0) + 1) *
|
pascal@17794
|
66 (parseInt(to.substring(1)) - parseInt(from.substring(1)) + 1)
|
pascal@17794
|
67 }
|
pascal@17794
|
68
|
pascal@17794
|
69 function zone(id,from,to,init,func) {
|
pascal@17794
|
70 var result=init
|
pascal@17794
|
71 for (var l=from.charCodeAt(0);;l++) {
|
pascal@17794
|
72 for (var n=parseInt(from.substring(1));
|
pascal@17794
|
73 n <= parseInt(to.substring(1));n++) {
|
pascal@17794
|
74 var e=document.getElementById(id+String.fromCharCode(l)+n)
|
pascal@17794
|
75 result=func(result,parseFloat(e.value))
|
pascal@17794
|
76 }
|
pascal@17794
|
77 if (l == to.charCodeAt(0)) break
|
pascal@17794
|
78 }
|
pascal@17794
|
79 return result;
|
pascal@17794
|
80 }
|
pascal@17794
|
81
|
pascal@15573
|
82 var DATA={};
|
pascal@15573
|
83 function buildCalc(id, rows, cols) {
|
pascal@15573
|
84 DATA[id] = {};
|
pascal@15573
|
85 var maths = [ "abs", "acos", "asin", "atan", "atan2", "ceil", "cos", "exp",
|
pascal@15573
|
86 "floor", "log", "max", "min", "pow", "random", "round", "sin",
|
pascal@15573
|
87 "tan", "sqrt", "PI", "E" ];
|
pascal@15573
|
88 for (var i=0; v = maths[i]; i++)
|
pascal@15573
|
89 eval("DATA[id]."+v+" = DATA[id]."+v.toUpperCase()+" = Math."+v);
|
pascal@15573
|
90 DATA[id].rand = DATA[id].RAND = Math.random;
|
pascal@15573
|
91 DATA[id].ln = DATA[id].LN = Math.log;
|
pascal@15573
|
92 DATA[id].log10= DATA[id].LOG10= function(n){return Math.log(n)/Math.LN10;};
|
pascal@15573
|
93 DATA[id].log2 = DATA[id].LOG2 = function(n){return Math.log(n)/Math.LN2;};
|
pascal@15573
|
94 DATA[id].fact = DATA[id].FACT =
|
pascal@15573
|
95 function(n){var x=1;while(n>1)x*=n--;return x;};
|
pascal@15573
|
96 DATA[id].fib = DATA[id].FIB =
|
pascal@15573
|
97 function(n){var c=0,p=1;while(n-->0){var x=c;c+=p;p=x};return c;};
|
pascal@17794
|
98 DATA[id].sum = DATA[id].SUM =
|
pascal@17794
|
99 function(a,b){return zone(id,a,b,0,function(a,b){return a+b});};
|
pascal@17794
|
100 DATA[id].min = DATA[id].MIN =
|
pascal@17794
|
101 function(a,b){return zone(id,a,b,Number.MAX_VALUE,Math.min);};
|
pascal@17794
|
102 DATA[id].max = DATA[id].MAX =
|
pascal@17794
|
103 function(a,b){return zone(id,a,b,Number.MIN_VALUE,Math.max);};
|
pascal@17794
|
104 DATA[id].cnt = DATA[id].CNT = cnt
|
pascal@15573
|
105 for (var i=0; i<=rows; i++) {
|
pascal@15573
|
106 var row = document.getElementById(id).insertRow(-1);
|
pascal@15573
|
107 for (var j=0; j<=cols && j<=26; j++) {
|
pascal@15573
|
108 var letter = String.fromCharCode("A".charCodeAt(0)+j-1);
|
pascal@15573
|
109 var cell = row.insertCell(-1);
|
pascal@15573
|
110 if (i&&j) {
|
pascal@15573
|
111 cell.className = "cellcalc";
|
pascal@15573
|
112 cell.innerHTML = "<input id='"+ id+letter+i +"' class='inputcalc'/>";
|
pascal@15573
|
113 }
|
pascal@15573
|
114 else {
|
pascal@15573
|
115 cell.className = "bordercalc";
|
pascal@15573
|
116 cell.title = "Show CSV";
|
pascal@15573
|
117 cell.onclick = function(){csv(id,rows,cols);};
|
pascal@15573
|
118 cell.innerHTML = (i||j) ? i||letter : "√";
|
pascal@15573
|
119 }
|
pascal@15573
|
120 }
|
pascal@15573
|
121 }
|
pascal@15573
|
122 }
|
pascal@15573
|
123
|
pascal@15573
|
124 function getWidth(s)
|
pascal@15573
|
125 {
|
pascal@15573
|
126 var e = document.getElementById("widthcalc");
|
pascal@17794
|
127 e.innerHTML = s;
|
pascal@15573
|
128 return (e.offsetWidth < 80 || s.charAt(0) == "=") ? 80 : e.offsetWidth;
|
pascal@15573
|
129 }
|
pascal@15573
|
130
|
pascal@15573
|
131 function setCell(e, v)
|
pascal@15573
|
132 {
|
pascal@15573
|
133 e.style.width = getWidth(v)+"px";
|
pascal@15573
|
134 e.style.textAlign =
|
pascal@15573
|
135 (isNaN(parseFloat(v)) && v.charAt(0) != "=") ? "left" : "right";
|
pascal@15573
|
136 e.title = v;
|
pascal@15573
|
137 }
|
pascal@15573
|
138 //-->
|
pascal@15573
|
139 </script>
|
pascal@15573
|
140 <span id="widthcalc" class="cellcalc" style="visibility:hidden;"></span>
|
pascal@15573
|
141 EOT;
|
pascal@15573
|
142 }
|
pascal@15573
|
143 $this->line[++$this->lines] = $current;
|
pascal@15573
|
144 $current = preg_replace("/</","<",$current);
|
pascal@15573
|
145 $i = count(explode(";", $current))-1;
|
pascal@15573
|
146 if ($this->lines == 1) $this->rows = $i;
|
pascal@15573
|
147 if ($i != $this->rows) $this->rows = -1;
|
pascal@15573
|
148 }
|
pascal@15573
|
149 else {
|
pascal@15573
|
150 if ($gotcalc) $this->showcalc();
|
pascal@15573
|
151 $this->newCONTENT .= $current."\n";
|
pascal@15573
|
152 }
|
pascal@15573
|
153 }
|
pascal@15573
|
154 if ($gotcalc) $this->showcalc();
|
pascal@15573
|
155 if ($showtail) {
|
pascal@15573
|
156 $this->newCONTENT .= <<<EOT
|
pascal@15573
|
157 <script type="text/javascript">
|
pascal@15573
|
158 <!--
|
pascal@15573
|
159 var INPUTS=[].slice.call(document.getElementsByClassName("inputcalc"));
|
pascal@15573
|
160 INPUTS.forEach(function(elm) {
|
pascal@15573
|
161 elm.onfocus = function(e) {
|
pascal@15573
|
162 e.target.value = e.target.title || "";
|
pascal@15573
|
163 };
|
pascal@15573
|
164 elm.onblur = function(e) {
|
pascal@15573
|
165 setCell(e.target, e.target.value);
|
pascal@15573
|
166 computeAll();
|
pascal@15573
|
167 };
|
pascal@15573
|
168 var calcid = elm.id.substring(0,4), cellid = elm.id.substring(4);
|
pascal@15573
|
169 var getter = function() {
|
pascal@15573
|
170 var value = elm.title || "";
|
pascal@15573
|
171 if (value.charAt(0) == "=")
|
pascal@15573
|
172 with (DATA[calcid]) return eval(value.substring(1));
|
pascal@17794
|
173 else return (value == "" || isNaN(value)) ? value : parseFloat(value);
|
pascal@15573
|
174 };
|
pascal@15573
|
175 Object.defineProperty(DATA[calcid], cellid, {get:getter});
|
pascal@15573
|
176 Object.defineProperty(DATA[calcid], cellid.toLowerCase(), {get:getter});
|
pascal@15573
|
177 });
|
pascal@15573
|
178 (window.computeAll = function() {
|
pascal@15573
|
179 INPUTS.forEach(function(elm) {
|
pascal@15573
|
180 var calcid = elm.id.substring(0,4), cellid = elm.id.substring(4);
|
pascal@15573
|
181 try { elm.value = DATA[calcid][cellid]; } catch(e) {} });
|
pascal@15573
|
182 })();
|
pascal@15573
|
183 //-->
|
pascal@15573
|
184 </script>
|
pascal@15573
|
185 EOT;
|
pascal@15573
|
186 }
|
pascal@15573
|
187 $CONTENT = $this->newCONTENT;
|
pascal@15573
|
188 }
|
pascal@15573
|
189
|
pascal@15573
|
190 function template()
|
pascal@15573
|
191 {
|
pascal@15573
|
192 global $html;
|
pascal@15573
|
193 $html = preg_replace("/<\/head>/",
|
pascal@15573
|
194 "\t<style type=\"text/css\"> @import \"plugins/wkp_Calc.css\"; </style>\n</head>",
|
pascal@15573
|
195 $html);
|
pascal@15573
|
196 }
|
pascal@15573
|
197 }
|
pascal@15573
|
198 ?>
|