1 
  2 /**
  3  * @name	CeL SVG function
  4  * @fileoverview
  5  * 本檔案包含了 SVG 的 functions。
  6  * @since	
  7  */
  8 
  9 
 10 /*
 11 TODO
 12 對無顯示 SVG 的多一項警告。
 13 
 14 ASCIIsvg.js
 15 http://www1.chapman.edu/~jipsen/svg/asciisvg.html
 16 */
 17 
 18 if (typeof CeL === 'function')
 19 CeL.setup_module('interact.integrate.SVG',
 20 {
 21 require : 'interact.DOM.XML_node|interact.DOM.set_attribute|interact.DOM.remove_all_child|interact.DOM.set_class|data.split_String_to_Object',
 22 code : function(library_namespace, load_arguments) {
 23 
 24 //	requiring
 25 var XML_node,set_attribute,remove_all_child,set_class,split_String_to_Object;
 26 eval(library_namespace.use_function(this));
 27 
 28 
 29 // ============================================================================
 30 //	definition of module SVG
 31 
 32 /*
 33 
 34 TODO:
 35 animation
 36 .add_image
 37 */
 38 
 39 //	in 運算子會檢查物件是否有名稱為 property 的屬性。它也會檢查物件的原型,查看 property 是否屬於原型鏈結的一部分。如果 property 是在物件或原型鏈結中,則 in 運算子會傳回 true,否則會傳回 false。	http://msdn2.microsoft.com/zh-tw/library/11e33275(VS.80).aspx
 40 
 41 //g_SVG[generateCode.dLK]='set_attribute,XML_node,remove_all_child';//removeNode
 42 
 43 /**
 44  * module SVG 物件之 constructor。<br/>
 45  * 設定 SVG document fragment 並將之插入網頁中。
 46 
 47  * @class	generation of Scalable Vector Graphics<br/>
 48  * 輔助繪圖的基本功能物件,生成 SVG 操作函數。
 49  * @since	2006/12/7,10-12
 50  * @deprecated	Use toolkit listed below instead:<br/>
 51  * <a href="http://code.google.com/p/svgweb/" accessdate="2009/11/15 16:34" title="svgweb - Project Hosting on Google Code">svgweb</a><br/>
 52  * <a href="https://launchpad.net/scour" accessdate="2009/11/15 16:35" title="Scour - Cleaning SVG Files in Launchpad">Scour</a>
 53 
 54  * @constructor
 55  * @param	{int} _width	width of the canvas
 56  * @param	{int} _height	height of the canvas
 57  * @param	{color String} [_backgroundColor]	background color of the canvas (UNDO)
 58  * @requires	set_attribute,XML_node,remove_all_child//removeNode
 59  * @type	CeL.interact.integrate.SVG
 60  * @return	{CeL.interact.integrate.SVG} CeL.interact.integrate.SVG object created
 61 
 62  * @see	<a href="http://www.w3.org/TR/SVG/" accessdate="2009/11/15 16:31">Scalable Vector Graphics (SVG) 1.1 Specification</a><br/>
 63  * <a href="http://zvon.org/xxl/svgReference/Output/" accessdate="2009/11/15 16:31">SVG 1.1 reference with examples</a><br/>
 64  * <a href="http://www.permadi.com/tutorial/jsFunc/index.html" accessdate="2009/11/15 16:31" title="Introduction and Features of JavaScript "Function" Objects">Introduction and Features of JavaScript "Function" Objects</a><br/>
 65  * <a href="http://volity.org/wiki/index.cgi?SVG_Script_Tricks" accessdate="2009/11/15 16:31">Volity Wiki: SVG Script Tricks</a><br/>
 66  * <a href="http://pilat.free.fr/english/routines/js_dom.htm" accessdate="2009/11/15 16:31">Javascript SVG et DOM</a>
 67  */
 68 CeL.interact.integrate.SVG
 69 = function(_width, _height, _backgroundColor){
 70  var _f = _, _s;
 71 /*
 72  if(!_f.createENS()){
 73   //alert('Your browser doesn't support SVG!');
 74   return;
 75  }
 76 */
 77 
 78  /**
 79   * SVG document fragment
 80   * @property
 81   * @see	<a href="http://www.w3.org/TR/SVG/struct.html#NewDocument" accessdate="2009/11/15 16:53">Defining an SVG document fragment: the 'svg' element</a>
 82   */
 83  this.svg=_s=	//	raw
 84 	arguments.length===1 && arguments[0] && typeof arguments[0]==='object' && arguments[0].tagName.toLowerCase()==='svg'
 85 	?arguments[0]
 86 	:_f.createNode('svg')
 87 	;
 88  if(!_s)return;	//	error!
 89 
 90  //	http://www.w3.org/TR/SVG/struct.html#DefsElement	http://www.svgbasics.com/defs.html
 91  _s.appendChild(this.defs=_f.createNode('defs'));	//	raw
 92 
 93  //	調整大小
 94  this.setSize(_width,_height);
 95  //	set_attribute(_s,{xmlns:_f.NS.SVG});
 96  set_attribute(_s,{xmlns:'http://www.w3.org/2000/svg'});
 97  //	may cause error! should use .setAttributeNS()??
 98  _s.setAttribute('xmlns:xlink','http://www.w3.org/1999/xlink');
 99  //viewBox="0 0 100 100" preserveAspectRatio="xMidYMid"
100 
101  /**
102   * 包含了插入元件的原始資訊。<br/>
103   * Use {@link #addContain} to add contains.
104   * @property
105   * @type	Array
106   */
107  this.contains = [];
108  /**
109   * 所插入之網頁元素
110   * @property
111   */
112  this.div = null;
113 
114  //document.body.appendChild(this.svg);
115  return this;//return this.createNode(_nodeN);
116 };
117 //_.NS={SVG:'http://www.w3.org/2000/svg',XLink:'http://www.w3.org/1999/xlink'};
118 _.defaultColor = '#222';
119 
120 CeL.interact.integrate.SVG
121 .
122 /**
123  * default stroke width. 單位: px
124  * 
125  * @unit px
126  * @type Number
127  * @memberOf CeL.interact.integrate.SVG
128  */
129 defaultStrokeWidth = .5;	
130 
131 //_.defaultColor='#444';_.defaultStrokeWidth=1;
132 
133 CeL.interact.integrate.SVG
134 .
135 /**
136  * 所有造出 id 之 prefix
137  * @type	string
138  * @memberOf	CeL.interact.integrate.SVG
139  */
140 idPrefix =
141 	// +'_SVG_';
142 	library_namespace.to_module_name(this.module_name) + '.';
143 
144 // _.bout closure.
145 //_.createENS=document.createElementNS?function(){return document.createElementNS(arguments[0],arguments[1]);}:null;
146 CeL.interact.integrate.SVG
147 .
148 /**
149  * create SVG document fragment (only for .createNode)
150  * @param _ns	namespaceURI
151  * @param _qn	qualifiedName
152  * @param _a	propertyA
153  * @param _i	innerObj
154  * @return
155  * @memberOf	CeL.interact.integrate.SVG
156  * @function
157  * @private
158  */
159 createENS = function(_ns, _qn, _a, _i) {
160 	return (
161 		// document.createElementNS?XML_node(_ns+':'+_qn,_a,0,_i):null;
162 		XML_node(_ns + ':' + _qn, _a, 0, _i));
163 };
164 
165 CeL.interact.integrate.SVG
166 .
167 /**
168  * create SVG document fragment 元件(component)。<br/>
169  * SVG 之 document fragment 與 HTML 不同 namespace,因此我們需要使用到 <a href="http://www.w3.org/2000/svg">http://www.w3.org/2000/svg</a> 來作為 XML elements 的 namespace。為了未來的兼容性,我們將這個功能獨立出來。
170  * @param _nodeN	node/tag name
171  * @param {hash|string}_a	attribute/property
172  * @param _i	inner object
173  * @return	node created or null
174  * @memberOf	CeL.interact.integrate.SVG
175  * @private
176  * @function
177  */
178 createNode = function(_nodeN,_a,_i){
179  //return this.createENS?this.createENS('svg',_nodeN||'svg'):null;
180  return _.createENS('svg', _nodeN || 'svg', _a, _i);
181 
182  //	Error: uncaught exception: [Exception... "Illegal operation on WrappedNative prototype object"  nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)"  location: "JS frame :: file:///C:/kanashimi/www/cgi-bin/program/tmp/JavaScript%20Framework/dojo/dojo-0.4.0-ajax/a.htm :: anonymous :: line 29"  data: no]
183  //	http://www.codingforums.com/archive/index.php?t-94573.html	When you do var x = document.getElementById and then x('hello') you are executing the function x in the context of the window object instead of the document object. Gecko probably utilizes the scoping of the document object to access some internal methods to execute getElementById, which the window object doesn't have.
184  //	http://developer.mozilla.org/en/docs/Safely_accessing_content_DOM_from_chrome	http://developer.mozilla.org/en/docs/Working_around_the_Firefox_1.0.3_DHTML_regression	http://www.codingforums.com/archive/index.php?t-68554.html
185  // OK?
186  //return this.createENS?this.createENS.call(document,'svg',_nodeN||'svg'):null;
187  // fault:
188  //return this.createENS===document.createElementNS?document.createElementNS('svg',_nodeN||'svg'):this.createENS?this.createENS('svg',_nodeN||'svg'):null;
189  //return this.createENS?(alert(this.createENS===document.createElementNS),Function.apply(this.createENS,['svg',(_nodeN||'svg')])):null;
190  //return this.createENS?(alert(this.createENS===document.createElementNS),this.createENS.apply(document.createElementNS,['svg',(_nodeN||'svg')])):null;
191 };
192 /*
193 _.createLink=function(_ref){
194  return this.createENS('xLink','xlink:href');
195 };
196 */
197 
198 CeL.interact.integrate.SVG
199 .
200 /**
201  * 從 id 獲得 node
202  * @param id	id
203  * @return	node
204  * @memberOf	CeL.interact.integrate.SVG
205  * @private
206  */
207 getNodeById = function(id) {
208 	// return this.svg.getElementById(_i);//useless?
209 
210 	// lookupPrefix()
211 	return document.getElementById(id);
212 };
213 
214 CeL.interact.integrate.SVG
215 .
216 /**
217  * get a random ID to use.
218  * @param tag	tag name(nodeType)
219  * @return	a random ID
220  * @memberOf	CeL.interact.integrate.SVG
221  * @private
222  */
223 getRandomID = function(tag) {
224 	if (typeof tag === 'object')
225 		tag = tag.tagName/* nodeType */;
226 	var _j;
227 	while (_.getNodeById(_j = _.idPrefix + tag + '_'
228 			+ ('' + Math.random()).slice(2, 6)))
229 		;
230 	return _j;
231 };
232 CeL.interact.integrate.SVG
233 .
234 /**
235  * give a random ID to the specified node.
236  * @param _n	node
237  * @return	id of the specified node
238  * @memberOf	CeL.interact.integrate.SVG
239  * @private
240  */
241 setRandomID = function(_n) {
242 	if (_n && typeof _n === 'object') {
243 		/**
244 		 * id of the specified node
245 		 * @inner
246 		 * @ignore
247 		 */
248 		var _i = set_attribute(_n, 'id');
249 		if (!_i)
250 			set_attribute(_n, {
251 				id : _i = _.getRandomID(_n)
252 			});
253 		return _i;
254 	}
255 };
256 
257 CeL.interact.integrate.SVG
258 .
259 /**
260  * 改變 text
261  * @param text_node	text object
262  * @param text	change to this text
263  * @return
264  * @memberOf	CeL.interact.integrate.SVG
265  * @see
266  * <a href="http://www.w3.org/TR/SVG/text.html" accessdate="2009/12/15 0:2">Text - SVG 1.1 - 20030114</a>
267  * <tref xlink:href="#ReferencedText"/>
268  */
269 changeText = function(text_node, text) {
270 	//if (typeof remove_all_child === 'function')
271 	//	remove_all_child(text_node);
272 	//else throw new Error(1, 'changeText: function remove_all_child is not included!');
273 	remove_all_child(text_node);
274 
275 	if (text)
276 		text_node.appendChild(document.createTextNode(text));
277 	//else removeNode(_textO);
278 };
279 
280 CeL.interact.integrate.SVG
281 .
282 addTitle = function(_o, _t_d) {
283 	if (_t)
284 		_o.appendChild(this.createNode('title', 0, _t));
285 	// A more descriptive label should be put in a <desc> child element
286 	if (_t)
287 		_o.appendChild(this.createNode('desc', 0, _t));
288 };
289 
290 
291 /*	transform	http://www.w3.org/TR/SVG/coords.html#TransformAttribute	http://archive.dojotoolkit.org/nightly/tests/gfx/test_image.html
292 recommend for performance reasons to use transformation matrices whenever possible.	http://www.mecxpert.de/svg/transform.html
293  * @memberOf	module SVG
294  */
295 CeL.interact.integrate.SVG
296 .
297 setTransform = function(_o, _t) {
298 	//	TODO
299 	throw new Error(1, 'setTransform: yet implement!');
300 	set_attribute(_o, {
301 				transform : _t
302 			});
303 };
304 
305 // ============================================================================
306 //	definition of module SVG object
307 
308 _.prototype={
309 
310 /**
311  * 顯現 this module SVG object
312  * @param _v	visible
313  * @return	this module SVG object
314  * @memberOf	CeL.interact.integrate.SVG
315  */
316 show : function(_v) {
317 	var _d = this.div;
318 	if (this.svg)
319 		if (_d) {// _s.parentNode
320 			_d.style.display = typeof _v == 'undefined' ? _d.style.display === 'none' ? 'block'
321 					: 'none'
322 						: _v ? 'block' : 'none'; // block怪怪的
323 		} else if (_v || typeof _v == 'undefined')
324 			this.div = XML_node('div', 0, [ document.body ],
325 					this.svg);
326 	return this;
327 },
328 setAttribute : function() {
329 	this.svg && this.svg.setAttribute(arguments);
330 	return this;
331 },
332 //setDimensions
333 /**
334  * 調整 canvas 大小
335  * @unit	px
336  * @param {Integer} _width	width in px
337  * @param {Integer} _height	height in px
338  * @return	this module SVG object
339  * @memberOf	CeL.interact.integrate.SVG
340  */
341 setSize : function(_width, _height) {
342 	_width = parseInt(_width) || 0;
343 	_height = parseInt(_height) || 0;
344 
345 	if (_width > 0 && _height > 0)
346 		set_attribute(this.svg, {
347 			width : _width,
348 			height : _height
349 		});
350 
351 	return this;
352 },
353 getSize : function() {
354 	return set_attribute(this.svg, 'width,height');
355 },
356 
357 /**
358  * 將本 Object 附在 _n 上(attach to node)
359  * @param _n	HTML/SVG object
360  * @return
361  */
362 attach : function(_n) {
363 	if (typeof _n === 'string')
364 		_n = _.getNodeById(_n);
365 
366 	if (!_n)
367 		return this;
368 
369 	var _t = _n.tagName.toLowerCase();
370 	if (_t === 'svg')
371 		//	TODO: 若不想創建新 node..
372 		return new _(_n);
373 
374 	if (_t === 'div') {
375 		//if(this.div){TODO: 原先已經 attach}
376 		this.div = _n;
377 		_n.appendChild(this.svg);
378 	}
379 
380 	return this;
381 },
382 
383 get_XML : function() {
384 	var _t = document.createElement('div'), _x, _s = this.svg;
385 
386 	if (!_s)
387 		// error!
388 		return;
389 
390 	//	TODO: 效率不高!
391 	_t.appendChild(_s = _s.cloneNode(true));
392 	_x = _t.innerHTML;
393 	_t.removeChild(_s);
394 	// 確保在此環境下 create 出來的會被 destory
395 	_t = null;
396 	// ugly hack
397 	// <?xml version="1.0" encoding="UTF-8" standalone="no"?>
398 	_x = _x.replace(/(\s)(href=['"])/g, '$1xlink:$2');
399 
400 	return _x;
401 },
402 
403 /**
404  * 清除 canvas<br/>
405  * 很可能會出問題!
406  * @return	this SVG
407  * @memberOf	CeL.interact.integrate.SVG
408  * @since	2009/12/18 21:17:09
409  */
410 clean : function() {
411 	var s = this.svg;
412 	//	[0]: <defs>
413 	while (s.childNodes.length > 1)
414 		//library_namespace.debug(s.childNodes.length + ',' + s.lastChild),
415 		s.removeChild(s.lastChild);
416 
417 	// remove childrens of <defs>
418 	//remove_all_child(s.lastChild, 1);
419 	s = s.lastChild;
420 	while (s.hasChildNodes())
421 		//library_namespace.debug(s.childNodes.length + ',' + s.lastChild),
422 		s.removeChild(s.lastChild);
423 
424 	return this;
425 },
426 
427 /**
428  * 創建本物件之 SVG 群組。<br/>
429  * 利用 SVG 群組我們可以同時操作多個 SVG elements。
430  * @param {hash|string}_a	attribute/property
431  * @param _i	inner object
432  * @return	this SVG
433  * @memberOf	CeL.interact.integrate.SVG
434  */
435 createGroup : function(_a, _i) {
436 	var _g = _.createNode('g', _a, _i);
437 	this.group = _g;
438 	return this;
439 },
440 /**
441  * 綁定 SVG elements 至本物件群組。<br/>
442  * 這函數將已存在的 SVG elements 綁定至本物件之群組中。若群組不存在,則創建出一個。
443  * @param _n	node
444  * @return	this module SVG object
445  * @memberOf	CeL.interact.integrate.SVG
446  */
447 attachGroup : function(_n) {
448 	if (!this.group)
449 		this.createGroup();
450 	this.group.appendChild(_n);
451 	return this;
452 },
453 
454 createSymbol : function(_a, _i) {
455 	var _s = _.createNode('symbol', _a, _i);
456 	this.symbol = _s;
457 	return this;
458 },
459 attachSymbol : function(_n) {
460 	if (!this.symbol)
461 		this.createSymbol();
462 	this.symbol.appendChild(_n);
463 	return this;
464 },
465 
466 //	TODO
467 setFill:function(){throw new Error(1,'setFill: yet implement!');},
468 setStroke:function(){throw new Error(1,'setStroke: yet implement!');},
469 setShape:function(){throw new Error(1,'setShape: yet implement!');},
470 setTransform:function(){throw new Error(1,'setTransform: yet implement!');},
471 
472 //<animateMotion>,<animateColor>
473 
474 /**
475  * 最後一個增加的 instance
476  * @memberOf	CeL.interact.integrate.SVG
477  */
478 lastAdd: null,
479 /**
480  * 最後一個增加的 definition
481  * @memberOf	CeL.interact.integrate.SVG
482  */
483 lastAddDefs: null,
484 /**
485  * 增加 SVG element。<br/>
486  * 結合 .prototype.addDefs 與 .prototype.addUse,作完定義後隨即使用之。
487  * @param _n	tagName(nodeType)
488  * @param {hash|string} _a	attribute/property
489  * @param _i	inner object
490  * @return
491  * @memberOf	CeL.interact.integrate.SVG
492  */
493 addNode : function(_n, _a, _i) {
494 	if (typeof _n == 'string')
495 		_n = _.createNode(_n, _a, _i);
496 	if (_n) {
497 		this.addDefs(_n);
498 		this.addUse(_n);
499 	}
500 	return this;
501 },
502 
503 /**
504  * 增加 SVG 定義。<br/>
505  * SVG 規範中聲明,SVG 的 <use> element 不能引用外部文件或其 elements。因此我們在創建實例之前,需要先在本物件中作定義。
506  * @param _n	node
507  * @return
508  * @memberOf	CeL.interact.integrate.SVG
509  */
510 addDefs : function(_n) {
511 	// var _d=this.defs;
512 	if (_n) {
513 		_.setRandomID(_n);
514 		this.defs.appendChild(this.lastAddDefs = _n);
515 	}
516 	return this;
517 },
518 /**
519  * 增加 SVG 實例。<br/>
520  * 利用本物件中之定義創建實例並增添至本物件中。<br/>
521  * 在裝載 b.svg 時,將 a.svg 中的 defs 中的圖元裝載到 b.svg 中(文件上是兩者是保持獨立的,但在內存中將二者合二為一),這樣就可以在b.svg中直接引用這些圖元了。<br/>
522  * SVG 規範中聲明,SVG 的 <use> element 不能引用外部文件或其 elements。因此我們在創建實例之前,需要先在本物件中作定義。
523  * @param _i	id
524  * @param _a
525  * @return
526  * @memberOf	CeL.interact.integrate.SVG
527  */
528 addUse : function(_i, _a) {
529 	var _s = this.svg, _o = _.createNode('use', _a);
530 	if (_o && _s && _i) {
531 		if (typeof _i == 'object')
532 			_i = _.setRandomID(_i);
533 		set_attribute(_o, {
534 			'xlink:href' : '#' + _i
535 		});
536 		_s.appendChild(this.lastAdd = _o);
537 	}
538 	return this;
539 },
540 
541 /**
542  * 增加插入的元件。<br/>
543  * 應該用 <a href="http://www.w3.org/TR/SVG/struct.html#SymbolElement">symbol</a>
544  * @param _o	object reference
545  * @param _type	type of this component
546  * @param [propertyO]	other properties
547  * @return
548  * @requires	split_String_to_Object
549  * @memberOf	CeL.interact.integrate.SVG
550  */
551 addContain : function(_o, _type, propertyO) {
552 	if (_type && this.contains) {
553 		if (typeof propertyO === 'string')
554 			propertyO = split_String_to_Object(propertyO);
555 		if (propertyO.o || propertyO.t)
556 			this.contains.push( {
557 				o : _o,
558 				t : _type,
559 				p : propertyO
560 			});
561 		else
562 			propertyO.o = _o, propertyO.t = _type, this.contains
563 			.push(propertyO);
564 	}
565 	return this;
566 },
567 
568 
569 /**
570  * 繪製直線。<br/>
571  * 此函數利用 _.eNode 造出直線元件之後,再用 .prototype.addNode 將之插入本物件中。
572  * @param _left
573  * @param _top
574  * @param _width
575  * @param _height
576  * @param _color
577  * @param _strokeWidth
578  * @return
579  * @memberOf	CeL.interact.integrate.SVG
580  */
581 addLine : function(_left, _top, _width, _height, _color,
582 		_strokeWidth) {
583 	var _l = _.createNode('line', {
584 		x1 : _top,
585 		y1 : _left,
586 		x2 : _top + _width,
587 		y2 : _left + _height,
588 		stroke : _color || this.addLine.defaultColor,
589 		'stroke-width' : _strokeWidth || _.defaultStrokeWidth
590 	});
591 	if (_l && this.svg) {
592 		//this.svg.appendChild(_l);
593 		this.addNode(_l);
594 	}
595 	return this;
596 },
597 
598 
599 /**
600  * 繪製曲線路徑。<br/>
601  * 此函數利用 _.eNode 造出路徑元件之後再用 .prototype.addNode 將之插入本物件中。
602  * @param _d
603  * @param _color
604  * @param _strokeWidth
605  * @param _fill
606  * @return
607  * @memberOf	CeL.interact.integrate.SVG
608  */
609 addPath : function(_d, _color, _strokeWidth, _fill) {
610 	var _p = _.createNode('path', {
611 		d : _d,
612 		stroke : _color || this.addLine.defaultColor,
613 		'stroke-width' : _strokeWidth || _.defaultStrokeWidth,
614 		fill : _fill || 'none'
615 	});
616 	if (_p && this.svg)
617 		this.addNode(_p);
618 	return this;
619 },
620 
621 
622 //xml:space="default|preserve"
623 /**
624  * 添加文字。<br/>
625  * 此函數利用 _.eNode 造出文字元件之後再用 .prototype.addNode 將之插入本物件中。
626  * @param _text
627  * @param _left
628  * @param _baseLine
629  * @param _color
630  * @param _font
631  * @return
632  * @memberOf	CeL.interact.integrate.SVG
633  */
634 addText : function(_text,_left,_baseLine,_color,_font){
635 	if (_color)
636 		this.addText.defaultColor = _color;
637 	else
638 		_color = this.addText.defaultColor;
639 
640 	if (_font)
641 		this.addText.defaultFont = _font;
642 	else
643 		_font = this.addText.defaultFont;
644 
645  //	http://www.w3.org/TR/SVG/text.html	<tref xlink:href="#ReferencedText"/>
646  //var _o=document.createTextNode(_text);
647  //var _o=_.createNode('tspan',{x:_left,y:_baseLine,stroke:_color||this.addText.defaultColor,style:_font?'font-family:"'+_font+'"':null},_text);
648  //this.addNode(_.createNode('text',{x:_left,y:_baseLine,stroke:_color||this.addText.defaultColor,style:_font?'font-family:"'+_font+'"':null},_o));
649  //this.lastAdd=_o;
650 
651 	// ugly hack: 說是_baseLine,其實還是會再往下一點點。
652 	_baseLine -= 2;
653 	this.addNode(_.createNode('text', {
654 		x : _left,
655 		y : _baseLine,
656 		stroke : _color || this.addText.defaultColor,
657 		style : _font ? 'font-family:"' + _font + '"' : null
658 	}, _text));
659 	//(text|g).pointer-events="none": Make text unselectable
660 
661 /*	本法為標準,但FF尚未支援。
662  var _s=this.svg,_i=_.getRandomID('text')_.SVG.createNode('text',{id:_i},_text);
663  this.addDefs(this.lastAddDefs=_o);
664  _o=_.createNode('text',{x:_left,y:_baseLine,stroke:_color||this.addText.defaultColor,style:_font?'font-family:"'+_font+'"':null},0,_t=_.createNode('tref'));
665  _t.setAttributeNS('xLink','xlink:href','#'+_i);
666  _o.appendChild(_t);
667  _s.appendChild(this.lastAdd=_o);
668 */
669 
670 	return this;
671 },
672 
673 /**
674  * add numbers
675  * @param _text
676  * @param _left
677  * @param _baseLine
678  * @param _tW
679  * @param _color
680  * @param _font
681  * @return
682  * @see
683  * _left: http://www.w3.org/TR/SVG/text.html#TSpanElementXAttribute
684  */
685 addNum : function(_text, _left, _baseLine, _tW, _color, _font) {
686 	if (!isNaN(_text)) {
687 		//	說是_baseLine,其實還是會再往下一點點。
688 		_baseLine -= 2;
689 		//_text=''+_text;
690 		_text += '';
691 
692 		var _o = [], _i = 0, _s = this.svg;
693 		for (; _i < _text.length; _i++)
694 			// _text.split('')
695 			_o.push(_.createNode('tspan', {
696 				x : _left + _i * _tW
697 				//, y:_baseLine
698 			}, _text.charAt(_i)));
699 
700 		if (_s)
701 			_s.appendChild(this.lastAdd = _.createNode('text', {
702 				y : _baseLine,
703 				stroke : _color || this.addText.defaultColor,
704 				style : _font ? 'font-family:"' + _font + '"'
705 						: null
706 			}, _o));
707 	}
708 	return this;
709 },
710 
711 
712 /**
713  * add parallel graph
714  * @param _ds
715  * @param _h
716  * @param _d
717  * @param _us
718  * @param tramA
719  * @return
720  * @since	2006/12/18 0:35
721  */
722 addParallelG : function(_ds, _h, _d, _us, tramA) {
723 	if (_ds && _h) {
724 		if (isNaN(_us) || _us === '')
725 			_us = _ds;
726 		set_attribute(this
727 				.addPath('M' + _ds + ',' + _h + ' H0 L' + (_d || 0)
728 						+ ',0' + (_us ? ' h' + _us : '') + ' z'), {
729 			transform : tramA
730 		}); //	0==''
731 	}
732 	return this;
733 },
734 
735 lastQuadrilateral : null,
736 lastQuadrilateralDefs : null,
737 /**
738  * 畫簡單長方形或平行四邊形、梯形
739  * @param _ds
740  * @param _h
741  * @param _d
742  * @param _us
743  * @param tramA
744  * @return
745  * @see	<a href="http://zh.wikipedia.org/wiki/%E5%B9%B3%E8%A1%8C%E5%9B%9B%E8%BE%B9%E5%BD%A2">平行四邊形</a>
746  * @memberOf	CeL.interact.integrate.SVG
747  */
748 addQuadrilateral:function(_ds,_h,_d,_us,tramA){	//	down side,height,upper distance,upper side
749  this.addParallelG(_ds,_h,_d,_us,tramA).addContain(this.lastQuadrilateralDefs=this.lastAddDefs,'quadrilateral',{down_side:_ds,hight:_h,distance:_d,upper_side:_us});
750  this.lastQuadrilateral=this.lastAdd;	//	set_attribute(s.lastQuadrilateral,'fill=none');
751  return this;
752 },
753 
754 lastTriangle : null,
755 lastTriangleDefs : null,
756 /**
757  * 畫簡單三角形
758  * @since	2006/12/17 12:38
759  * @param _ds
760  * @param _h
761  * @param _d
762  * @param tramA
763  * @return
764  * @memberOf	CeL.interact.integrate.SVG
765  */
766 addTriangle : function(_ds, _h, _d, tramA) {
767 	this.addParallelG(_ds, _h, _d, 0, tramA).addContain(
768 			this.lastTriangleDefs = this.lastAddDefs, 'triangle', {
769 				down_side : _ds,
770 				hight : _h,
771 				distance : _d
772 			});
773 	this.lastTriangle = this.lastAdd;
774 	return this;
775 },
776 
777 
778 /**
779  * 繪製橢圓曲線。<br/>
780  * 此函數利用 _.eNode 造出橢圓曲線元件之後,再用 .prototype.addNode 將之插入本物件中。
781  * @param _rx
782  * @param _ry
783  * @param _cx
784  * @param _cy
785  * @param _color
786  * @param _strokeWidth
787  * @param _fill
788  * @param tramA
789  * @return
790  * @memberOf	CeL.interact.integrate.SVG
791  */
792 addEllipsePath : function(_rx, _ry, _cx, _cy, _color, _strokeWidth,
793 		_fill, tramA) {
794 	if (_rx) {
795 		var _e, _p = {
796 				rx : _rx,
797 				ry : _ry,
798 				cx : _cx,
799 				cy : _cy,
800 				stroke : _color || this.addEllipsePath.defaultColor,
801 				'stroke-width' : _strokeWidth || _.defaultStrokeWidth,
802 				fill : _fill || 'none',
803 				transform : tramA
804 		};
805 
806 		if (!_ry)
807 			_e = 'circle', _p.r = _rx;
808 		else
809 			_e = 'ellipse', _p.rx = _rx, _p.ry = _ry;
810 
811 		_e = _.createNode(_e, _p);
812 
813 		if (_e && this.svg)
814 			this.addNode(_e);
815 	}
816 	return this;
817 },
818 
819 
820 lastCircle : null,
821 lastCircleDefs : null,
822 /**
823  * 繪製圓形。<br/>
824  * 此函數利用 _.type.addEllipsePath 來畫簡單圓形。
825  * @param _r
826  * @param _cx
827  * @param _cy
828  * @return
829  * @memberOf	CeL.interact.integrate.SVG
830  */
831 addCircle : function(_r, _cx, _cy) {
832 	if (_r)
833 		this.addEllipsePath(_r, '', _cx, _cy).addContain(
834 				this.lastCircleDefs = this.lastAddDefs, 'circle', {
835 					r : _r
836 				});
837 	return this;
838 },
839 
840 lastEllipse : null,
841 lastEllipseDefs : null,
842 /**
843  * 繪製簡單圓形/橢圓。<br/>
844  * 此函數利用 .prototype.addEllipsePath 來畫簡單橢圓。
845  * @param _rx
846  * @param _ry
847  * @param _cx
848  * @param _cy
849  * @return
850  * @memberOf	CeL.interact.integrate.SVG
851  */
852 addEllipse : function(_rx, _ry, _cx, _cy) {
853 	if (_rx) {
854 		this.addEllipsePath(_rx, _ry, _cx, _cy).addContain(
855 				this.lastEllipseDefs = this.lastAddDefs, 'ellipse',
856 				{
857 					rx : _rx,
858 					ry : _ry
859 				});
860 		this.lastEllipse = this.lastAdd;
861 	}
862 	return this;
863 },
864 
865 
866 /**
867  * 繪製矩形。<br/>
868  * 此函數利用 _.eNode 造出矩形路徑元件之後,再用 .prototype.addNode 將之插入本物件中。
869  * @param _w
870  * @param _h
871  * @param _x
872  * @param _y
873  * @param _color
874  * @param _strokeWidth
875  * @param _fill
876  * @param tramA
877  * @return
878  * @memberOf	CeL.interact.integrate.SVG
879  */
880 addRect : function(_w, _h, _x, _y, _color, _strokeWidth, _fill,
881 		tramA) {
882 	this.addNode(_.createNode('rect', {
883 		width : _w,
884 		height : _h,
885 		x : _x,
886 		y : _y,
887 		stroke : _color || this.addRect.defaultColor,
888 		'stroke-width' : _strokeWidth || _.defaultStrokeWidth,
889 		fill : _fill || 'none',
890 		transform : tramA
891 	}));
892 	return this;
893 },
894 
895 
896 /**
897  * 繪製多邊形。<br/>
898  * 此函數利用 _.eNode 造出多邊形路徑元件之後再用 .prototype.addNode 將之插入本物件中。
899  * @param {int array} _pA	[x1,y1,x2,y2,x3,y3,..]
900  * @param _color
901  * @param _strokeWidth
902  * @param _fill
903  * @param tramA
904  * @return
905  * @memberOf	CeL.interact.integrate.SVG
906  */
907 addPolyline : function(_pA, _color, _strokeWidth, _fill, tramA) {
908 	var _i = 0, _p = [];
909 	while (_i < _pA.length)
910 		_p.push(_pA[_i++] + ',' + _pA[_i++]);
911 	this.addNode(_.createNode('polyline', {
912 		points : _p.join(' '),
913 		stroke : _color || this.addRect.defaultColor,
914 		'stroke-width' : _strokeWidth || _.defaultStrokeWidth,
915 		fill : _fill || 'none',
916 		transform : tramA
917 	}));
918 	return this;
919 },
920 
921 
922 addImage : function() {
923 	//	TODO
924 	throw new Error(1, 'addImage: yet implement!');
925 },
926 
927 /**
928  * 功能正常嗎?
929  * @return	{Boolean} 功能正常
930  */
931 status_OK : function() {
932 	// !!: dual-unary operator
933 	return !!this.svg;
934 }
935 
936 };	//	_.prototype={
937 
938 
939 //	other manual setting
940 with (_.prototype) {
941 	addLine.defaultColor = _.defaultColor;
942 	addPath.defaultColor = _.defaultColor;
943 	addText.defaultColor = _.defaultColor;
944 	addText.defaultFont = null;
945 	addEllipsePath.defaultColor = _.defaultColor;
946 	addRect.defaultColor = _.defaultColor;
947 	addPolyline.defaultColor = _.defaultColor;
948 
949 }
950 
951 //	↑definition of module SVG object
952 
953 //	↑definition of module SVG
954 // ============================================================================
955 
956 
957 /**#@+
958  * @description	use {@link CeL.interact.integrate.SVG} to draw:
959  */
960 
961 /*
962 draw_circle[generateCode.dLK]
963 	=draw_ellipse[generateCode.dLK]
964 	=draw_triangle[generateCode.dLK]
965 	=draw_quadrilateral[generateCode.dLK]
966 	='g_SVG';
967 */
968 
969 CeL.interact.integrate.SVG
970 .
971 /**
972  * 繪製圓形。
973  * @since	2006/12/19 18:05
974  * @param _r
975  * @param svgO
976  * @param _color
977  * @param _fill
978  * @return	module SVG object
979  * @memberOf	CeL.interact.integrate.SVG
980  */
981 draw_circle = function(_r, svgO, _color, _fill) {
982 	var g_SVG = library_namespace.interact.integrate.SVG;
983 	if (_r
984 			&& (svgO || (svgO = new g_SVG(
985 					(_r + g_SVG.defaultStrokeWidth) * 2,
986 					(_r + g_SVG.defaultStrokeWidth) * 2).show()))
987 					&& svgO.status_OK()) {
988 		svgO.addCircle(_r, _r + g_SVG.defaultStrokeWidth, _r
989 				+ g_SVG.defaultStrokeWidth);
990 		return svgO;
991 	}
992 };
993 CeL.interact.integrate.SVG
994 .
995 /**
996  * 繪製橢圓。
997  * @param _rx
998  * @param _ry
999  * @param svgO
1000  * @param _color
1001  * @param _fill
1002  * @return	module SVG object
1003  * @memberOf	CeL.interact.integrate.SVG
1004  */
1005 draw_ellipse = function(_rx, _ry, svgO, _color, _fill) {
1006 	var g_SVG = library_namespace.interact.integrate.SVG;
1007 	if (_rx
1008 			&& _ry
1009 			&& (svgO || (svgO = new g_SVG(
1010 					(_rx + g_SVG.defaultStrokeWidth) * 2,
1011 					(_ry + g_SVG.defaultStrokeWidth) * 2).show()))
1012 					&& svgO.status_OK()) {
1013 		svgO.addEllipse(_rx, _ry, _rx + g_SVG.defaultStrokeWidth, _ry
1014 				+ g_SVG.defaultStrokeWidth);
1015 		return svgO;
1016 	}
1017 };
1018 
1019 
1020 CeL.interact.integrate.SVG
1021 .
1022 /**
1023  * 畫簡單梯形。
1024  * @since	2006/12/17 12:38
1025  * @requires	split_String_to_Object,set_attribute,XML_node,removeNode,remove_all_child,g_SVG,draw_quadrilateral
1026  * @param _ds
1027  * @param _h
1028  * @param _d
1029  * @param _us
1030  * @param svgO
1031  * @param _color
1032  * @param _fill
1033  * @return	module SVG object
1034  * @memberOf	CeL.interact.integrate.SVG
1035  */
1036 draw_quadrilateral = function(_ds, _h, _d, _us, svgO, _color, _fill) {
1037 	var g_SVG = library_namespace.interact.integrate.SVG;
1038 	if (isNaN(_us) || _us === '')
1039 		_us = _ds;
1040 	if (_ds
1041 			&& _h
1042 			&& (svgO || (svgO = new g_SVG((_ds > _d + _us ? _ds : _d
1043 					+ _us)
1044 					+ g_SVG.defaultStrokeWidth, _h
1045 					+ g_SVG.defaultStrokeWidth).show()))
1046 					&& svgO.status_OK()) {
1047 		set_attribute(svgO.addQuadrilateral(_ds, _h, _d, _us).lastQuadrilateral,
1048 				{
1049 			stroke : _color,
1050 			fill : _fill
1051 				});
1052 		return svgO;
1053 	}
1054 };
1055 
1056 CeL.interact.integrate.SVG
1057 .
1058 /**
1059  * 畫簡單三角形。
1060  * @since	2006/12/17 12:38
1061  * @requires	split_String_to_Object,set_attribute,XML_node,removeNode,remove_all_child,g_SVG,draw_triangle
1062  * @param _ds
1063  * @param _h
1064  * @param _d
1065  * @param svgO
1066  * @param _color
1067  * @param _fill
1068  * @return	module SVG object
1069  * @memberOf	CeL.interact.integrate.SVG
1070  */
1071 draw_triangle = function(_ds, _h, _d, svgO, _color, _fill) {
1072 	var g_SVG = library_namespace.interact.integrate.SVG;
1073 	if (_ds
1074 			&& _h
1075 			&& (svgO || (svgO = new g_SVG((_ds > _d ? _ds : _d)
1076 					+ g_SVG.defaultStrokeWidth, _h
1077 					+ g_SVG.defaultStrokeWidth).show()))
1078 					&& svgO.status_OK()) {
1079 		set_attribute(svgO.addTriangle(_ds, _h, _d).lastTriangleDefs, {
1080 			stroke : _color,
1081 			fill : _fill
1082 		});
1083 		return svgO;
1084 	}
1085 };
1086 
1087 /*
1088 draw_addition[generateCode.dLK]
1089 	=draw_multiplication[generateCode.dLK]
1090 	=draw_long_division[generateCode.dLK]
1091 	='g_SVG,draw_scale';
1092 */
1093 
1094 /**
1095  * default 畫筆。
1096  * @inner
1097  * @private
1098  */
1099 var draw_scale = {
1100 		/**
1101 		 * text width
1102 		 * @inner
1103 		 * @private
1104 		 */
1105 		tW : 10,
1106 		/**
1107 		 * text height
1108 		 * @inner
1109 		 * @private
1110 		 */
1111 		tH : 2 * (10/* tW */- 2),
1112 		/**
1113 		 * decimal separator, 小數點
1114 		 * @see
1115 		 * <a href="http://en.wikipedia.org/wiki/Decimal_separator" accessdate="2010/1/20 18:29">Decimal separator</a>
1116 		 */
1117 		ds : '.',
1118 		/**
1119 		 * width of decimal separator
1120 		 */
1121 		dsw : 4,
1122 		/**
1123 		 * line height
1124 		 * @inner
1125 		 * @private
1126 		 */
1127 		lH : 4,
1128 		/**
1129 		 * margin left
1130 		 * @inner
1131 		 * @private
1132 		 */
1133 		mL : 0,
1134 		/**
1135 		 * margin top
1136 		 * @inner
1137 		 * @private
1138 		 */
1139 		mT : 0,
1140 		/**
1141 		 * 根號寬, squire width
1142 		 * @inner
1143 		 * @private
1144 		 */
1145 		sW : 10
1146 };
1147 //draw_scale.tH=22,draw_scale.tW=12;	//	for print
1148 CeL.interact.integrate.SVG
1149 .
1150 /**
1151  * 利用 module SVG 物件來演示直式加法。
1152  * @since	2006/12/26 17:47
1153  * @param num1
1154  * @param num2
1155  * @param svgO
1156  * @param _color
1157  * @param _font
1158  * @return	module SVG object
1159  * @memberOf	CeL.interact.integrate.SVG
1160  */
1161 draw_addition=function(num1, num2, svgO, _color, _font) {
1162 	if (!num1 && !num2)
1163 		return;
1164 	var g_SVG = library_namespace.interact.integrate.SVG;
1165 	var _op = '+';
1166 	if (num2 < 0)
1167 		_op = '-', num2 = -num2;
1168 
1169 	var _a = _op == '+' ? (num1 - 0) + (num2 - 0) : num1 - num2,
1170 	_h = 3,
1171 	_w = (num2 += '').length + 2,
1172 	tW = draw_scale.tW,
1173 	tH = draw_scale.tH,
1174 	lH = draw_scale.lH,
1175 	mL = draw_scale.mL,
1176 	mT = draw_scale.mT;
1177 
1178 	if ((_a += '').length + 1 > _w)
1179 		_w = _a.length + 1;
1180 	if ((num1 += '').length + 1 > _w)
1181 		_w = num1.length + 1;
1182 	_h = _h * tH + 2 * lH + 2 * mT;
1183 	_w = (2 + _w) * tW + 2 * mL;
1184 
1185 	if (svgO && svgO.status_OK())
1186 		svgO.clean();
1187 	else if (!(svgO = new g_SVG).show().status_OK())
1188 		return null;
1189 
1190 	svgO.setSize(_w, _h);
1191 
1192 	_w -= mL + tW;
1193 
1194 	//	TODO: 讓 IE8 顯示起來像 111+111=222, 而非 +111111222
1195 	svgO
1196 		.addNum(num1, _w - num1.length * tW, mT + tH, tW, _color, _font)
1197 		.addNum(num2, _w - num2.length * tW, mT + 2 * tH, tW, _color, _font)
1198 		.addText(_op, mL + tW, mT + 2 * tH, _color, _font)
1199 		.addPath('M' + mL + ',' + (mT + 2 * tH + lH / 2) + ' H' + (_w + tW))
1200 		.addNum(_a, _w - _a.length * tW, mT + 3 * tH + lH, tW, _color, _font);
1201 
1202 	return svgO;
1203 };
1204 //draw_subtraction[generateCode.dLK]='draw_addition';
1205 CeL.interact.integrate.SVG
1206 .
1207 /**
1208  * 呼叫 draw_subtraction 來演示直式減法。因為直式加減法的運算與機制過程非常相似,因此我們以 draw_addition 來一併的處理這兩個相似的運算過程。
1209  * @since	2006/12/26 17:47
1210  * @param num1
1211  * @param num2
1212  * @param svgO
1213  * @param _color
1214  * @param _font
1215  * @return	module SVG object
1216  * @memberOf	CeL.interact.integrate.SVG
1217  */
1218 draw_subtraction = function(num1, num2, svgO, _color, _font) {
1219 	return _.draw_addition.call(this, num1, -num2, svgO, _color, _font);
1220 };
1221 
1222 CeL.interact.integrate.SVG
1223 .
1224 /**
1225  * 利用 module SVG 物件來演示直式乘法。<br/>
1226  * TODO: 小數的乘法
1227  * @since	2006/12/26 17:47
1228  * @param num1
1229  * @param num2
1230  * @param svgO
1231  * @param _color
1232  * @param _font
1233  * @return	module SVG object
1234  * @memberOf	CeL.interact.integrate.SVG
1235  * @see
1236  * <a href="http://203.71.239.19/math/courses/cs04/M4_6.php" accessdate="2010/1/20 18:5">小數篇:小數的乘法</a>
1237  */
1238 draw_multiplication=function(num1, num2, svgO, _color, _font) {
1239 	if (!num1 && !num2)
1240 		return;
1241 
1242 	var g_SVG = library_namespace.interact.integrate.SVG;
1243 	var _op = '×', _j, _C = 1, _a = num1 * num2, _h = 0, _w = (num2 += '').length + 2, tW = draw_scale.tW, tH = draw_scale.tH, lH = draw_scale.lH, mL = draw_scale.mL, mT = draw_scale.mT;
1244 	if ((_a += '').length > _w)
1245 		_w = _a.length;
1246 	if ((num1 += '').length > _w)
1247 		_w = num1.length;
1248 	for (_j = 0; _j < num2.length; _j++)
1249 		if (num2.charAt(_j) - 0)
1250 			_h++;
1251 	if (_h == 1)
1252 		_h = 0, _C = 0;
1253 	_h = (3 + _h) * tH + 2 * lH + 2 * mT;
1254 	_w = (2 + _w) * tW + 2 * mL;
1255 
1256 	if (svgO && svgO.status_OK())
1257 		svgO.clean();
1258 	else if (!(svgO = new g_SVG).show().status_OK())
1259 		return null;
1260 
1261 	svgO.setSize(_w, _h);
1262 
1263 	_w -= mL + tW;
1264 
1265 	svgO
1266 		.addNum(num1, _w - num1.length * tW, mT + tH, tW, _color, _font)
1267 		.addNum(num2, _w - num2.length * tW, mT + 2 * tH, tW, _color, _font)
1268 		.addText(_op, mL + tW, mT + 2 * tH, _color, _font)
1269 		.addPath('M' + mL + ',' + (_h = mT + 2 * tH + lH / 2) + ' H' + (_w + tW));
1270 
1271 	_op = '';
1272 	_h += lH / 2;
1273 	var _w2 = _w, _n;
1274 	if (_C) {
1275 		for (_j = num2.length - 1; _j >= 0; _j--)
1276 			if (_n = num2.charAt(_j) - 0)
1277 				svgO.addNum(_n = (num1 * _n) + _op, _w2 - _n.length
1278 						* tW, _h += tH, tW, _color, _font), _w2 -= tW
1279 						* (_op.length + 1), _op = '';
1280 			else
1281 				_op += '0';
1282 		svgO
1283 		.addPath('M' + mL + ',' + (_h += lH / 2) + ' H'
1284 				+ (_w + tW));
1285 	}
1286 
1287 	svgO.addNum(_a, _w - _a.length * tW, _h + lH / 2 + tH, tW, _color, _font);
1288 
1289 	return svgO;
1290 };
1291 
1292 /*
1293 TODO:
1294 小數
1295 換基底
1296 */
1297 //draw_long_division[generateCode.dLK]='g_SVG,set_class';//split_String_to_Object,set_attribute,XML_node,removeNode,remove_all_child,g_SVG,draw_long_division
1298 CeL.interact.integrate.SVG
1299 .
1300 /**
1301  * 利用 module SVG 物件來展示<a href="http://en.wikipedia.org/wiki/Long_division" title="long division">直式除法</a>。<br/>
1302  * !! 尚有許多 bug<br/>
1303  * @since	2006/12/11-12 11:36
1304  * @param dividend
1305  * @param divisor
1306  * @param	digits_after	TODO: 小數直式除法: 小數點後位數, how many digits after the decimal separator
1307  * @param svgO
1308  * @param _color
1309  * @param _font
1310  * @return	module SVG object
1311  * @example
1312  * // include module
1313  * CeL.use('net.SVG');
1314  * 
1315  * //	way 1
1316  * var SVG_object = new CeL.SVG;
1317  * SVG_object.attach('panel_for_SVG').show(1);
1318  * CeL.draw_long_division(452, 34, SVG_object);
1319  * // You can also put here.
1320  * //SVG_object.attach('panel_for_SVG').show(1);
1321  * 
1322  * //	way 2
1323  * var SVG_object = CeL.draw_long_division(100000, 7);
1324  * SVG_object.attach('panel_for_SVG').show(1);
1325  * 
1326  * // 另一次顯示
1327  * CeL.draw_long_division(100, 7, SVG_object);
1328  * @memberOf	CeL.interact.integrate.SVG
1329  */
1330 draw_long_division = function(dividend, divisor, svgO, _color, _font) {
1331 	if (isNaN(dividend) || isNaN(divisor) || !divisor)
1332 		return;
1333 
1334 	var g_SVG = library_namespace.interact.integrate.SVG;
1335 	/**
1336 	 * 餘數 remainder
1337 	 * @inner
1338 	 * @ignore
1339 	 */
1340 	var remainder;
1341 	/**
1342 	 * 商 quotient
1343 	 * @inner
1344 	 * @ignore
1345 	 */
1346 	var quotient = '' + Math.floor(dividend / divisor),
1347 		tW = draw_scale.tW,
1348 		tH = draw_scale.tH,
1349 		lH = draw_scale.lH,
1350 		mL = draw_scale.mL,
1351 		mT = draw_scale.mT,
1352 		sW = draw_scale.sW,
1353 		bx = mL + ('' + divisor).length * tW + sW,
1354 		by = mT + lH + 2 * tH;
1355 
1356 	dividend += '';
1357 	if (svgO && svgO.status_OK())
1358 		svgO.clean();
1359 	else if (!(svgO = new g_SVG).show().status_OK())
1360 		return null;
1361 
1362 	svgO
1363 	//.show(1)
1364 	// 調整大小
1365 	.setSize(
1366 			2
1367 			* mL
1368 			+ (('' + divisor).length + dividend.length + 2)
1369 			* tW + sW,
1370 			2 * mT + by + quotient.length * (tH * 2 + lH))
1371 	// 除數 divisor
1372 	.addNum(divisor, mL, by, tW, _color, _font)
1373 	// 商 quotient
1374 	.addNum(quotient,
1375 			bx + (dividend.length - quotient.length) * tW,
1376 			mT + tH, tW, _color, _font)
1377 	// 被除數 dividend
1378 	.addNum(dividend, bx, by, tW, _color, _font)
1379 	// .addNode('path',{d:'M'+(bx+(dividend.length+1)*tW)+','+(by-lH/2-tH)+'
1380 	// H'+(bx-tW)+' a'+tW/2+','+(lH+tH)+' 0 0,1
1381 	// -'+tW/2+','+(lH+tH),stroke:'#000',style:'fill:none;'})
1382 	.addPath(
1383 			'M' + (bx - (tW + sW) / 2) + ',' + (by + lH / 2)
1384 			+ ' a' + tW / 2 + ',' + (lH + tH)
1385 			+ ' 0 0,0 ' + tW / 2 + ',-' + (lH + tH)
1386 			+ ' h' + (dividend.length + 2) * tW);
1387 
1388 	svgO.addDefs(g_SVG.createNode('line', {
1389 		x1 : 0,
1390 		y1 : 0,
1391 		x2 : (dividend.length + 1) * tW,
1392 		y2 : 0,
1393 		// 'stroke-width':'1px',
1394 		stroke : svgO.addLine.defaultColor
1395 	}));
1396 
1397 	if (svgO.div)
1398 		// svgO.div.className='long_division';
1399 		set_class(svgO.div, 'long_division');
1400 
1401 	// 用 symbol??
1402 	svgO.addContain(0, 'long_division', {
1403 		dividend : dividend,
1404 		divisor : divisor
1405 	});
1406 
1407 	var _k = 0, a, b, l = svgO.lastAddDefs,
1408 	/**
1409 	 * 被除數處理到第幾位
1410 	 * @inner
1411 	 * @ignore
1412 	 */
1413 	dt = 1;
1414 	remainder = dividend.charAt(0);
1415 	for (; _k < quotient.length;) {
1416 		a = quotient.charAt(_k);
1417 		// if(!a)continue;
1418 		a = '' + a * divisor, b = dividend.length
1419 		- quotient.length + _k + 1;
1420 
1421 		svgO.addUse(l, {
1422 			x : bx,
1423 			y : (by + tH + lH / 2)
1424 		}).addNum(a, bx + (b - a.length) * tW, by + tH, tW, _color,
1425 				_font);
1426 
1427 		// 以下..ugly hack
1428 		// 先算出餘數
1429 		while ((a == 0 || remainder - a < 0) && dt < dividend.length)
1430 			remainder += dividend.charAt(dt++);
1431 		remainder -= a;
1432 		if (!remainder)
1433 			remainder = '';
1434 		//alert(remainder+','+quotient.charAt(_k+1)+'\n'+(i<quotient.length))
1435 		// 再添加到夠減的位數
1436 		while (quotient.charAt(++_k) == 0 && _k < quotient.length) {
1437 			b++;
1438 			if (remainder || dividend.charAt(dt) > 0)
1439 				remainder += dividend.charAt(dt);
1440 			dt++;
1441 		}
1442 		// 顯示位數微調
1443 		if (dt < dividend.length) {
1444 			b++;
1445 			// 加一位
1446 			remainder += dividend.charAt(dt++);
1447 		} else if (!remainder)
1448 			b--;
1449 		//alert(remainder+','+a+','+dt+'\n'+(remainder<a));
1450 		svgO.addNum(remainder || 0, bx + (b - ('' + remainder).length)
1451 				* tW, by += 2 * tH + lH, tW, _color, _font);
1452 	}
1453 
1454 	return svgO;
1455 };
1456 
1457 
1458 /**#@-*/
1459 //	↑@memberOf	module SVG
1460 
1461 
1462 
1463 
1464 
1465 
1466 return (
1467 	CeL.interact.integrate.SVG
1468 );
1469 }
1470 
1471 
1472 });
1473 
1474