      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