1. 程式人生 > >單頁Web應用 4 新增功能模組

單頁Web應用 4 新增功能模組

    功能模組向單頁應用提供了精心定義和有作用域限制的功能。除了聊天滑塊之外,還有其他功能模組的例子,包括圖片檢視器、賬戶管理面板或者是使用者集中放置圖形物件的工作臺。

    和第三方模組的做法很像:精心定義的API和強隔離性。可在多個專案之間很容易地重用模組。

4.1 功能模組策略

     模組有自己的檢視、控制器和Shell在它們之間共享的部分模型。

     功能模組的例子包括在工作臺上處理草圖的spa.wb.js、管理賬戶功能的spa.acct.js(像登入或登出)和用於聊天介面的spa.chat.js。


     與第三方模組的比較:參考《Third-Party JavaScript》

          包括部落格評論姓(DisQus或者LiveFyre)、廣告型的(DoubleClick或者ValueClick)、分析型的(Google或者Overture)、分享型的(AddThis或ShareThis)和社交服務型的(贊)。它們都非常流行,因為網站管理員可以把這些高質量的功能新增到他們的網站裡面,和自己來開發這些功能相比。

          精心編寫的第三方模組具有以下共同特徵:

  • 在自己的容器內渲染
  • 提供了精心定義的API,以便控制它們的行為
  • 通過將自己的JavaScript、資料和CSS精心地隔離,避免汙染主頁面

           它的缺點也有多。

          我們的功能模組沒有使用第三方模組,向Shell提供一致的配置、初始化和呼叫的API。通過使用唯一的和協調的JavaScript和CSS名字空間,功能之間相互隔離,除了共享的工具方法外,不允許任何外部呼叫。

         像第三方模組一樣來開發自己的模組,還有一個巨大的優勢:我們處於一種有利的情況,Web應用的非核心功能使用第三方模組,然後在時間和資源允許時,有選擇性地使用自己的功能模組來替換它們,這樣就能更好地整合、執行更快、侵入性更小,或者是以上全部的好處。

      功能模組和分型MVC模式:分形是一種模式,它在所有層級上顯示為自相似性。我們的單頁應用架構在多個層級上採用重複的MVC模式,所以我們把它叫做”分形模型-檢視-控制器“,或者是FMVC

      應用被分割為兩部分:伺服器採用MVC模式向客戶端提供資料;採用MVC的單頁應用允許使用者檢視瀏覽器的模型,並與之互動。伺服器的模型是從資料庫獲取的資料,而檢視是要傳送給瀏覽器的資料表現,控制器是協調資料管理和同瀏覽器通訊的程式碼。在客戶端,模型包括從伺服器接收到的資料,檢視是使用者介面,控制器是協調客戶端資料和介面的邏輯。


      幾乎所有的現代網站都適用這種模式,即便開發人員沒有意識到這一點。比如,一旦開發人員把DisQus或者LiveFyre的評論模組新增到他們的部落格中,他們就添加了另外一個MVC模式。

4.2 建立功能模組檔案

      規劃檔案結構

  • 為Chat模組建立一個有名字空間的樣式表
  • 為Chat模組建立一個有名字空間的JavaScript模組js/spa.chat.js,js/spa.model.js
  • 為瀏覽器端的模型建立一個樁檔案(stub)css/spa.chat.css
  • 建立一個提供通用程式的共用模組,供其他所有模組使用js/spa.util.js。
  • 修改瀏覽文件,引入新的檔案。
  • 刪除用來開發佈局的檔案。

      樁檔案:css/spa.chat.css,樁是一個故意沒有完成的或者是佔位用的資源

      文件載入約定:根-》核心工具方法-》Model-》瀏覽器端工具方法-》Shell-》功能模組

      為什麼自己的庫要放在最後載入,因為防止第三方庫宣告名字空間spa.model。

4.3 設計方法API

      功能模組之間的相互呼叫是不允許的。功能模組的唯一資料來源或者功能只能來自Shell,在配置和初始化期間以引數的形式傳給模組的公開方法。

      錨介面模式


       Chat的配置API:JS中所有複雜資料型別(物件、陣列和函式)傳遞的是引用。

  1. 一個提供”修改URI錨中的chat引數"的功能的函式
  2. 一個提供“傳送和接收訊息(來自model)”的方法的物件
  3. 一個提供“與一系列使用者(來自Model)互動”的方法的物件。
  4. 許多行為設定,比如滑塊開啟時的高度,滑塊的開啟時間以及滑塊的關閉時間。

        js/spa.chat.js中API規範, configModele, 

       配置和初始化的級聯:所有的模組都有公開的initModule方法。只在需要支援設定時,才會提供configModule方法。

4.4 實現功能API

       樣式表:css/spa.chat.css


       修改Chat:API實現。js/spa.chat.js

4.5 新增經常使用的方法

      重置方法(removeSlider)和視窗尺寸變化的方法(handleResize)

      如果使用者登出的時候,徹底移除聊天滑塊。需要刪除Chat新增的DOM容器,依次釋放初始化和配置資訊。

      視窗有些情況下不能工作,需要一些計算。

spa.html

<!doctype html>
<html>
<head>
  <!-- ie9+ rendering support for latest standards -->
  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <title>SPA Chapter 4</title>
  <!-- third-party stylesheets -->

  <!-- our stylesheets -->
  <link rel="stylesheet" href="css/spa.css" type="text/css" />
  <link rel="stylesheet" href="css/spa.chat.css" type="text/css" />
  <link rel="stylesheet" href="css/spa.shell.css" type="text/css" />

  <!-- third-party javascript -->
  <script src="js/jq/jquery-3.2.1.js" ></script>
  <script src="js/jq/jquery.uriAnchor.js" ></script>

  <!-- our javascript -->
  <script src="js/spa.js" ></script>
  <script src="js/spa.util.js" ></script>
  <script src="js/spa.model.js" ></script>
  <script src="js/spa.shell.js" ></script>
  <script src="js/spa.chat.js" ></script>
  <script>
    $(function () { 
    	spa.initModule( $('#spa') );
    });
  </script>
</head>
<body>
  <div id="spa"></div>
</body>
</html>
css/spa.css
/** 重置大多數選擇器,我們不信任瀏覽器的預設行為 */
* {
	margin:  0;
	padding: 0;
	-webkit-box-sizing : border-box;
	-moz-box-sizing    : border-box;
	box-sizing         : border-box;
}
h1, h2, h3, h4, h5, h6, p { margin-bottom: 6pt ; }
o1, ul, dl { list-style-position : inside ; }

/** 希望確保跨平臺應用有一致的外觀。 */
body {
	font : 13px 'Trebuchet MS', Verdana, Helvetica, Arial, sans-serif;
	color   : # 444;
	background-color: #888;
}
a {
	text-decoration: none;
}
a:link, a:visited { color : inherit; }
a:hover { text-decoration : underline; }

strong {
	font-weight:  800;
	color : #000;
}

/** 通常使用根名字作為元素選擇器,定義選擇器的名字空間*/
#spa {
	position    : absolute;
	top         : 0;
	left        : 0;
	bottom      : 0;
	right       : 0;

	min-height: 15em;
	min-width: 35em;
	overflow : hidden;

	background : #fff;
}

/** 其他模組,以spa-x-作為字首*/
.spa-x-select {}
.spa-x-clearfloat {
	height      : 0       !important;
	float       : none    !important;
	visibility  : hidden  !important;
	clear       : both    !important;
}
css/spa.shell.css
.spa-shell-head, .spa-shell-head-logo, .spa-shell-head-acct,
.spa-shell-head-search, .spa-shell-main, .spa-shell-main-nav, 
.spa-shell-main-content, .spa-shell-foot, 
.spa-shell-modal {
	position : absolute;
}
.spa-shell-head {
	top     : 0;
	left    : 0;
	right   : 0;
	height  : 40px;
}
.spa-shell-head-logo {
	top     : 4px;
	left    : 4px;
	right   : 32px;
	width   : 128px;
	background  : orange;
}
.spa-shell-head-acct {
	top     : 4px;
	right    : 0;
	height   : 32px;
	width   : 64px;
	background  : green;
}
.spa-shell-head-search {
	top     : 4px;
	right    : 64px;
	height   : 32px;
	width   : 248px;
	background  : blue;
}
.spa-shell-main {
	top     : 40px;
	left    : 0;
	right   : 0;
	bottom  : 40px;
}
.spa-shell-main-content,
.spa-shell-main-nav {
	top     : 0px;
	bottom  : 0px;
}
.spa-shell-main-nav {
	width     : 250px;
	background  : #eee;
}/*使用父類來影響子元素。這大概是CSS的一個最強大的功能,但幾乎沒被頻繁的使用*/
  .spa-x-closed,
  .spa-shell-main-nav {
   	  width     : 0px;
  }
  
.spa-shell-main-content {
	left    : 250px;
	right   : 0;
	background  : #ddd;
}/*縮排派生選擇器,緊跟在父選擇器的下面*/
  .spa-x-closed,
  .spa-shell-main-content {
	  left     : 0px;
  }
.spa-shell-foot {
	height     : 40px;
	left    : 0;
	right   : 0;
	bottom  : 0;
}

.spa-shell-modal {
	margin-top : -200px;
    margin-left : -200px;
    top     : 50%;
    left :   50%;
	width   : 400px;
	height  : 400px;
	background : #fff;
	z-index  : 2;
	display : none;
}
css/spa.chat.css
/* Chat feature styles
 */

.spa-chat {
	position:  absolute;
	bottom: 0;
	right: 0;
	width: 25em;
	height: 2em;
	background: #fff;
	border-radius: 0.5em 0 0 0;
	border-style: solid;
	border-width: thin 0 0 thin;
	border-color: #888;
	box-shadow: 0 0 0.75em 0 #888;
	z-index : 1 ;
}

.spa-chat-head, spa-chat-closer {
	position: absolute;
	top     : 0;
	height: 2em;
	line-height: 1.8em;
	border-bottom: thin solid #888;
	cursor   : pointer;
	background : #888;
	color: white;
	font-family: arial, helvetica, sans-serif;
	font-weight: 800;
	text-align: center;
}

.spa-chat-head {
	left: 0;
	right: 2em;
	border-radius: 0.3em 0 0 0;
}

.spa-chat-closer {
	right: 0;
	width: 2em;
}
  .spa-chat-closer:hover {
  	background: #800;
  }

.spa-chat-head-toggle {
	position: absolute;
	top: 0;
	left: 0;
	width: 2em;
	bottom: 0;
	border-radius: 0.3em 0 0 0;
}

.spa-chat-head-title {
	position: absolute;
	left: 50%;
	width: 16em;
	margin-left: -8em;
}

.spa-chat-sizer {
	position: absolute;
	top: 2em;
	left: 0;
	right: 0;
}

.spa-chat-msgs {
	position: absolute;
	top: 1em;
	left: 1em;
	right: 1em;
	bottom: 4em;
	padding: 0.5em;
	border : thin solid #888;
	overflow-x: hidden;
	overflow-y: scroll;
}

.spa-chat-box {
	position: absolute;
	height: 2em;
	left: 1em;
	right: 1em;
	bottom: 1em;
	border : thin solid #888;
	background: #888;
}

.spa-chat-box input[type=text] {
	float: left;
	width: 75%;
	height: 100%;
	padding: 0.5em;
	border : 0;
	background: #ddd;
	color: #404040;
}
  .spa-chat-box input[type=text]:focus {
  	background: #fff;
  }

.spa-chat-box div {
	float: left;
	width: 25%;
	height: 2em;
	line-height: 1.9em;
	text-align: center;
	color: #fff;
	font-weight: 800;
	cursor: pointer;
}
  .spa-chat-box div:hover {
  	background-color: #444;
  	color: #ff0;
  }

.spa-chat-head:hover .spa-chat-head-toggle {
	background: #aaa;
}
js/spa.js
/*jslint    browser : true, continue : true,
    devel : true, indent : 2, maxerr : 50,
    newcap : true, nomen : true, plusplus : true,
    regexp : true, sloppy : true, vars : true,
    white : true
*/

var spa = (function ( ) {
	// 初始化
	var initModule = function ( $container ) {
		spa.shell.initModule( $container );
	};
	return { initModule : initModule };  //返回spa名字空間中的物件,只匯出了initModele方法
}());
js/spa.shell.js
/*jslint    browser : true, continue : true,
    devel : true, indent : 2, maxerr : 50,
    newcap : true, nomen : true, plusplus : true,
    regexp : true, sloppy : true, vars : true,
    white : true
*/
spa.shell = (function () {
	var configMap = {
		anchor_schema_map : { 
			chat : {opened : true, closed : true }
		},
		main_html : String() 
		  + '<div class="spa-shell-head">'
		    + '<div class="spa-shell-head-logo"></div>'
		    + '<div class="spa-shell-head-acct"></div>'
		    + '<div class="spa-shell-head-search"></div>'
		  + '</div>'
		  + '<div class="spa-shell-main">'
		    + '<div class="spa-shell-main-nav"></div>'
		    + '<div class="spa-shell-main-content"></div>'
		  + '</div>'
		  + '<div class="spa-shell-foot"></div>'
		  + '<div class="spa-shell-modal"></div>',
		resize_interval : 200
	},
	stateMap = { 
		anchor_map  : {},
		resize_idto : undefined
	},  /*在整個模組中共享的動態資訊*/
	jqueryMap = { },
	setJqueryMap,  initModule, 
	copyAnchorMap, changeAnchorPart, 
	onHashchange,  setChatAnchor, onResize;
	// 將建立和操作頁面元素的函式放在"DOM Methods"區塊中
	copyAnchorMap = function () {
		return $.extend( true, {}, stateMap.anchor_map );
	};
	changeAnchorPart = function (arg_map) {
		var anchor_map_revise = copyAnchorMap();
		var bool_return = true;
		var key_name, key_name_dep;
		KEYVAL:
		for (key_name in arg_map) {
			if (arg_map.hasOwnProperty( key_name )) {
				if (key_name.indexOf('_') === 0) { continue KEYVAL; }
				anchor_map_revise[key_name] = arg_map[key_name];
				key_name_dep = '_' + key_name;
				if (arg_map[key_name_dep]) {
					anchor_map_revise[key_name_dep] = arg_map[key_name_de];
				} else {
					delete anchor_map_revise[key_name_dep];
					delete anchor_map_revise['_s' + key_name_dep];
				}
			}
		}
		//
		try {
			$.uriAnchor.setAnchor( anchor_map_revise );
		} catch (error) {
			$.uriAnchor.setAnchor( stateMap.anchor_map, null, true );
			bool_return = false;
		}
		return bool_return;
	};
	onHashchange = function (event) {
		var anchor_map_previous = copyAnchorMap();
		var anchor_map_proposed, _s_chat_previous;
		var _s_chat_proposed, s_chat_proposed;
		var is_ok = true;
		//
		try {
			anchor_map_proposed = $.uriAnchor.makeAnchorMap(); 
		} catch (error) {
			$.uriAnchor.setAnchor( anchor_map_previous, null, true );
			return false;
		}
		stateMap.anchor_map = anchor_map_proposed;
		//
		_s_chat_previous = anchor_map_previous._s_chat;
		_s_chat_proposed = anchor_map_proposed._s_chat;
		//
		if ( ! anchor_map_previous 
			|| _s_chat_previous !== _s_chat_proposed ) {
			s_chat_proposed = anchor_map_proposed.chat;
		    switch (s_chat_proposed) {
		    	case 'opened':
		    	  is_ok = spa.chat.setSliderPosition('opened');
		    	break;
		    	case 'closed':
		    	  is_ok = spa.chat.setSliderPosition('closed');
		    	break;
		    	default:
		    	is_ok = spa.chat.setSliderPosition('closed');
		    	delete anchor_map_proposed.char;
		    	$.uriAnchor.setAnchor( anchor_map_proposed, null, true );
		    }
		}
		if (!is_ok) {
			if (anchor_map_previous) {
				$.uriAnchor.setAnchor( anchor_map_previous, null, true );
				stateMap.anchor_map = anchor_map_previous;
			} else {
				delete anchor_map_proposed.chat;
				$.uriAnchor.setAnchor( anchor_map_proposed, null, true );
			}
		}
		return false;
	};
	// Event handler
	onResize = function () {
		if (stateMap.resize_idto) { return true; }
		spa.chat.handleResize();
		stateMap.resize_idto = setTimeout(
			function () {
				stateMap.resize_idto = undefined;
			}, configMap.resize_interval 
		);
		return true;
	};

	// Begin DOM Methods
	setJqueryMap = function () {    
	    //快取jQuery集合,幾乎我們編寫的每個Shell和功能模組都應該有這個函式
	    //可以大大地減少jQuery對文件的遍歷次數,能夠提高效能。
		var $container = stateMap.$container;
		jqueryMap = { 
			$container : $container
		};
	};


    setChatAnchor = function (position_type) {
    	return changeAnchorPart(
    		{ chat : position_type }
    	);
    }
	initModule = function ( $container ) {
		stateMap.$container  = $container;
		$container.html( configMap.main_html );
		setJqueryMap();

		$.uriAnchor.configModule( {
			schema_map : configMap.anchor_schema_map
		});
		// configure and initialize feature modules
		spa.chat.configModule( {
			chat_model : spa.model.chat,
			set_chat_anchor : setChatAnchor,
			people_model : spa.model.people
		} );
		spa.chat.initModule( jqueryMap.$container );
		//
		$(window) 
		   .bind( 'hashchange', onHashchange )
		   .trigger( 'hashchange' );
	};
	return { initModule : initModule };
} ());

js/spa.util.js

/*jslint    browser : true, continue : true,
    devel : true, indent : 2, maxerr : 50,
    newcap : true, nomen : true, plusplus : true,
    regexp : true, sloppy : true, vars : true,
    white : true
*/

spa.util = (function () {
	var makeError, setConfigMap;
	makeError = function ( name_text, msg_text, data ) {
		var error     = new Error();
		error.name    = name_text;
		error.message = msg_text;
		if (data) {
			error.data = data;
		}
		return error;
	};
	setConfigMap = function (arg_map) {
		var input_map = arg_map.input_map;
		var settable_map  = arg_map.settable_map;
		var config_map = arg_map.config_map;
		var key_name, error;

		for ( key_name in input_map ) {
			if (input_map.hasOwnProperty( key_name ) ) {
				if (settable_map.hasOwnProperty( key_name ) ) {
					config_map[key_name] = input_map[key_name];
				} else {
					error = makeError( 'Bad Input', 'Setting config key |' + key_name + '| is not supported');
					throw error;
				}
			}
		}
	};

	return {
		makeError     : makeError,
		setConfigMap  : setConfigMap
	};
}());
js/spa.model.js
/*jslint    browser : true, continue : true,
    devel : true, indent : 2, maxerr : 50,
    newcap : true, nomen : true, plusplus : true,
    regexp : true, sloppy : true, vars : true,
    white : true
*/

spa.model = (function () {
	return {};
}());
js/spa.chat.js
/*jslint    browser : true, continue : true,
    devel : true, indent : 2, maxerr : 50,
    newcap : true, nomen : true, plusplus : true,
    regexp : true, sloppy : true, vars : true,
    white : true
*/

/*spa.chat名字空間*/
spa.chat = (function () {
	var configMap = {
		main_html : String() 
		  + '<div class="spa-chat">'
		    + '<div class="spa-chat-head">'
		      + '<div class="spa-chat-head-toggle"> + </div>'
		      + '<div class="spa-chat-head-title">'
		        + 'Chat'
		      + '</div>'
		    + '</div>'
		    + '<div class="spa-chat-closer">x</div>'
		    + '<div class="spa-chat-sizer">'
		      + '<div class="spa-chat-msgs"></div>'
		      + '<div class="spa-chat-box">'
		        + '<input type="text"/>'
		        + '<div>send</div'
		      + '</div>'
		    + '</div>'
		  + '</div>',
		settable_map : { 
			slider_open_time   : true,
			slider_close_time  : true,
			slider_opened_em   : true,
			slider_closed_em   : true,
			slider_opened_title : true,
			slider_closed_title : true,

			chat_model     : true,
			people_model   : true,
			set_chat_anchor  :true
		},
		slider_open_time   : 250,
		slider_close_time  : 250,
		slider_opened_em   : 18,
		slider_closed_em   : 2,
		slider_opened_title : 'Click to close',
		slider_closed_title : 'Click to open',
		slider_opened_min_em : 10,   //最小高度
		window_height_min_em : 20,

		chat_model   : null,
		people_model : null,
		set_chat_anchor : null
	},
	stateMap = { 
		$append_target  : null,
		position_type   : 'closed',
		px_per_em       : 0,
		slider_hidden_px : 0,
		slider_closed_px : 0,
		slider_opened_px : 0 
	},
	jqueryMap = {

	},
	setJqueryMap, configModule, initModule,
	getEmSize, setPxSizes, setSliderPosition,
	onClickToggle, removeSlider, handleResize;
	//Begin utility methods
	getEmSize = function ( elem ) {
		return Number(
			getComputedStyle( elem, '' ).fontSize.match(/\d*\.?\d*/)[0]
		);
	};

	//Begin DOM method 
	setJqueryMap = function() {
		var $append_target = stateMap.$append_target;
		var $slider = $append_target.find('.spa-chat');
		jqueryMap = { 
			$slider    : $slider,
			$head      : $slider.find('.spa-chat-head'),
			$toggle    : $slider.find('.spa-chat-head-toggle'),
			$title     : $slider.find('.spa-chat-head-title'),
			$sizer     : $slider.find('.spa-chat-sizer'),
			$msgs      : $slider.find('.spa-chat-msgs'),
			$box       : $slider.find('.spa-chat-box'),
			$input     : $slider.find('.spa-chat-input input[type-text]') 
		};
	};
	setPxSizes = function () {
		var px_per_em, opened_height_em, window_height_em;
		px_per_em = getEmSize( jqueryMap.$slider.get(0) );
		window_height_em = Math.floor( ( $(window).height() / px_per_em ) + 0.5 );
		opened_height_em = window_height_em > configMap.window_height_min_em 
		  ? configMap.slider_opened_em 
		  : configMap.slider_opened_min_em;
		//opened_height_em = configMap.slider_opened_em;
		stateMap.px_per_em = px_per_em;
		stateMap.slider_closed_px = configMap.slider_closed_em * px_per_em;
		stateMap.slider_opened_px = opened_height_em * px_per_em;
		jqueryMap.$sizer.css ( {
			height  : (opened_height_em - 2) * px_per_em
		});
	};
	handleResize = function () {
		if (!jqueryMap.$slider) { return false; }
		setPxSizes();
		if (stateMap.position_type === 'opened') {
			jqueryMap.$slider.css({
 				height : stateMap.slider_opened_px
			});
		}
		return true;
	};

	setSliderPosition = function (position_type, callback) {
		var height_px, animate_time, slider_title, toggle_text;
		if (stateMap.position_type === position_type) {
			return true;
		}
		switch (position_type) {
			case 'opened':
			   height_px = stateMap.slider_opened_px;
			   animate_time = configMap.slider_open_time;
			   slider_title = configMap.slider_opened_title;
			   toggle_text = '=';
			break;

			case 'hidden':
			   height_px = 0;
			   animate_time = configMap.slider_open_time;
			   slider_title = '';
			   toggle_text = '+';
			break;

			case 'closed':
			   height_px = stateMap.slider_closed_px;
			   animate_time = configMap.slider_close_time;
			   slider_title = configMap.slider_closed_title;
			   toggle_text = '+';
			break;

			default : return false;
		}
		// animate slider position change
		stateMap.positiong_type = '';
		jqueryMap.$slider.animate(
       		{ height : height_px },
       		animate_time,
       		function () {
       			jqueryMap.$toggle.prop('title', slider_title);
       			jqueryMap.$toggle.text( toggle_text );
       			stateMap.position_type = position_type;
       			if (callback) { callback( jqueryMap.$slider ); }
       		}
		);
		return true;
	};
	//Begin event handlers
	onClickToggle = function ( event ) {
		var set_chat_anchor = configMap.set_chat_anchor;
		if (stateMap.position_type === 'opened') {
			set_chat_anchor('closed');
		} else if (stateMap.position_type === 'closed') {
			set_chat_anchor('opened');
		}
		return false;
	};

	//Begin public methods
	configModule = function ( input_map ) {
		spa.util.setConfigMap({
			input_map    : input_map,
			settable_map : configMap.settable_map,
			config_map   : configMap
		});
		return true;
	};
	//
	removeSlider = function () {
		if (jqueryMap.$slider) {
			jqueryMap.$slider.remove();
			jqueryMap = {};
		}
		stateMap.$append_target = null;
		stateMap.position_type = 'closed';
		// unwind key configurations
		configMap.chat_model = null;
		configMap.people_model = null;
		configMap.set_chat_anchor = null;
		return true;
	};
	initModule = function ( $append_target ) {
		$append_target.append( configMap.main_html );
		stateMap.$append_target = $append_target;
		setJqueryMap();
		setPxSizes();

		jqueryMap.$toggle.prop('title', configMap.slider_closed_title);
		jqueryMap.$head.click( onClickToggle );
		stateMap.position_type = 'closed';
		return true;
	};
	//這兩個方法幾乎是所有功能模組的標配方法
	return {
		setSliderPosition : setSliderPosition,
		configModule : configModule,
		initModule   : initModule,
		removeSlider : removeSlider,
		handleResize : handleResize
	};
}());