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