article:
tag:
just test

Javascript > 设计一个通用脚本库(Javascript) by shawl.qiu 上一篇 | 下一篇

SqCsJsLib, js, javascript, shawl.qiu

设计一个通用脚本库(Javascript) by shawl.qiu

说明:
什么是通用脚本库?
其实嘛, 就是一个管理N个Js资源的程序.

必要解释:
脚本库不是框架, 脚本框架那一套鄙人并不认为是一种好的方法.
框架实现的兼容方法导致写的程序脱离框架基本无法使用.
而脚本库是每一独立程序组合成一个程序集合, 可拆可合.

设计宗旨:
实现使用 Js 资源有下面的特色:
可复用, 简单调用, 保密性(对新手), 可扩展, 版本兼容, 具说明性.


严格点说, 应该是说明脚本库程序的运行方式, 因为下面我要说明的这个脚本库程序, 其实已经设计完毕.

运作方式使用类似 c# 的 import 方式导入需要的脚本.
比如在 /Lib/UI/Dragging/ 目录下, 有 Dragging.js
Lib 是库目录, 那么可以这样导入
Im.Include('UI.Dragging'true);
参数 true 是防止重复导入, 具体说明请看下文.


现在从设计顺序逐步说明:
1. 脚本库结构
2. 命名规则
3. 库类具体功能
4. 实现库类(/SqCsJsLib/default.js)
5. 库类调用参考
6. 库类调用结构及优先顺序说明

shawl.qiu
2007-11-29
http://btbtd.cublog.cn/

下载示例库:
http://blogimg.chinaunix.net/blog/upfile2/071129013710.zip

示例库说明:
里面含有几个曾经发布过的类, 至于本库目前的脚本类数量为近百, 大部分为未发布, 目前不打算发布(用来Make Money)...
库中库类 .htm 文件带有 Lib 字符的即是库调用示例, 没有为类调用示例.

设计顺序

1. 脚本库结构

首先, 我们要定义脚本库的名字, 叫 SqCsJsLib.
具体意思 shawl.qiu Client-Side Javascript Library

SqCsJsLib 应当放在网站根目录, 非必须, 但这样容易管理调用.

使用二级分类法存放内容.
一级分类为不同脚本用途的文件夹, 二级分类为具体脚本类文件夹

SqCsJsLib 下有N个文件夹(一级分类), 如
/SqCsJsLib/Alg/
/SqCsJsLib/Dom/
/SqCsJsLib/Form/
/SqCsJsLib/Editor/
/SqCsJsLib/Event/
/SqCsJsLib/Ui/

上面文件夹的用途是存放不同用途的脚本内容, 一级分类下存放着具体脚本文件夹, 如 /SqCsJsLib/Ui/ 目录下有:
/SqCsJsLib/Ui/Dragging/
/SqCsJsLib/Ui/Rounded/
/SqCsJsLib/Ui/XMenu/

就是说, 存放着三个脚本类.

具体脚本类文件夹下为 FolderName.js, 此即为脚本类.
如 /SqCsJsLib/Ui/Dragging/ 下必定有 Dragging
如 /SqCsJsLib/Ui/XMenu/ 下必定有 XMenu

2. 命名规则

命名规则主要针对二级分类, 也就是具体脚本类, 目的为实现版本兼容.

比如 你在 /SqCsJsLib/Ui/ 下已有脚本类 Rounded
即: /SqCsJsLib/Ui/Rounded/, 版本为 1.0

你现在有一个升级版本 Rounded 2.0, 所以你想把 Rounded 1.0 替换掉, 可是现在的项目已经运行有一阵子, 调用该类还相当频繁, 如果要逐个更改调用方法将会非常麻烦, 那怎么办, 嗯, 这样办:
在 /SqCsJsLib/Ui/ 下建立一个文件夹 Rounded2 或 Rounded2-0
或 Rounded-2-0 或 Rounded_2-0

呵呵, 啰嗦了这么多, 其实是想说明, 在二级分类行末的某些字符在调用具体脚本类时会被忽略掉, 比如 "-", "_", "0-9".

现在 Rounded 2.0 目录为:
/SqCsJsLib/Ui/Rounded2/, 下面有文件 Rounded.js

可这样即可:
Im.Include('UI.Rounded2'true);

至于具体操作, 那是库类的事情.

3. 库类具体功能

3.1 实现直接导入功能(即不依赖库目录), 防止重复导入.
3.2 从库结构导入, 防止重复导入.
3.3 帮助功能, 可高亮显示帮助内容.

4. 实现库类(/SqCsJsLib/default.js)


/* <script> */

var Im = new Importer();
 Im.Go(fInitImporter);
 
function fInitImporter(Param)
{
 Param.Path = "/SqCsJsLib/";
 Param.Ext = ".js";
 
 Param.HFolder = "Help";
 Param.HExt = ".txt";
 
 Param.HIntervalMs = 50;
}

// shawl.qiu JavaScript Document
/*-----------------------------------------------------------------------------------*\
 * shawl.qiu Javascript Importer class v1.0
\*-----------------------------------------------------------------------------------*/

//---------------------------------begin class Importer()-------------------------------//
function Importer()
{// shawl.qiu code
 //------------------------------------begin private variable
 //---------------begin about
 var Au = {};
  Au.Subject = "shawl.qiu Javascript Importer class";
  Au.Version = "v1.1";
  Au.Name = "shawl.qiu";
  Au.Email = "shawl.qiu@gmail.com";
  Au.Blog = "http://blog.csdn.net/btbtd/";
  Au.CreatedDate = "2007-9-13 v1.0";
  Au.Update = {};
  Au.Update["1"] = "2007-9-29 v1.1";
 //---------------end about
 
 var This = this;
 
 var Param = {};
 Param.Path = "/SqCsJsLib/";
 Param.Ext = ".js";
 
 Param.HFolder = "Help";
 Param.HExt = ".txt";
 
 Param.HIntervalMs = 50;
 
 var PVar = {};
 PVar.Interval = null;
 PVar.Count = 0;
 //------------------------------------end private variable
 
 //------------------------------------begin public method
 //-------------------Begin this.Get
 this.Get = {};
 this.Get.Au = fGetAu;
 //-------------------End this.Get
 
 //-------------------Begin this.Set
 this.Set = {};
 //-------------------End this.Set
 
 this.Go = fGo;
 this.Include = fInclude;
 this.IncludeDirector = fIncludeDirector;
 this.Help = fHelp;
 //------------------------------------end public method

 //------------------------------------begin private method
 function fGo(fIniter)
 { // shawl.qiu code, void return
  if(fIsFunc(fIniter)) fIniter(Param);
 } // end function fGo
 
 function fIncludeDirector(sCmdList, bIncludeOnce)
 { // shawl.qiu code, void return
  var CmdAr = sCmdList.split("|");
  var CmdArLen = CmdAr.length;
  var iCmdArCount = 0;
  
  while(iCmdArCount<CmdArLen)
  {
   var sFilePath = CmdAr[iCmdArCount];
   var sClass = sFilePath.replace(/^.*\//g, "").replace(/\..*$/g, "");
   
   var bIncluded = false;
   
   if(bIncludeOnce)
   {
    bIncluded = fIsFunc(window[sClass]);
    
    //document.write("bIncluded: ", bIncluded, "<br/>");
    
    if(bIncluded) 
    {
     iCmdArCount++
     continue;
    }
   } // end if
   
   var sInclude =  ["<script type='text/javascript' src='",sFilePath,"'><\/script>"].join('');
   document.write(sInclude);
   //defaultStatus = sFilePath;
   
   iCmdArCount++;
  } // end while
 } // end function fIncludeDirector(sCmdList, bIncludeOnce)
 
 function fInclude(sCmdList, bIncludeOnce)
 { // shawl.qiu code, return array
  var CmdAr = sCmdList.split("|");
  var CmdArLen = CmdAr.length;
  var iCmdArCount = 0;
  var PathAr = [];
  
  while(iCmdArCount<CmdArLen)
  {
   var sCmd = CmdAr[iCmdArCount];
   var sPath = sCmd.replace(/\./g, "/");
   var sClass = sCmd.replace(/^.*\./g, "").replace(/[\d\_\-]+$/"");
   var sFilePath = [Param.Path, sPath, "/", sClass, Param.Ext].join("");
   var sFolderPath = [Param.Path, sPath, "/"].join("");
   
   PathAr.push(sFolderPath);
   
   var bIncluded = false;
   
   if(bIncludeOnce)
   {
    bIncluded = fIsFunc(window[sClass]);
    
    //document.write("bIncluded: ", bIncluded, "<br/>");
    
    if(bIncluded) 
    {
     iCmdArCount++
     continue;
    }
   } // end if
   
//    document.write("sCmd: ", sCmd, "<br/>");
//    document.write("sPath: ", sPath, "<br/>");
//    document.write("sClass: ", sClass, "<br/>");
//    document.write("sFilePath: ", sFilePath, "<br/>");
   
   var sInclude =  ["<script type='text/javascript' src='",sFilePath,"'><\/script>"].join('');
   document.write(sInclude);
   
   iCmdArCount++;
  } // end while
  return PathAr;
 } // end function fInclude(sCmdList, bIncludeOnce)
 
 function fHelp(sCmdList, bHighlight)
 { // shawl.qiu code, void return
  var CmdAr = sCmdList.split("|");
  var CmdArLen = CmdAr.length;
  var iCmdArCount = 0;
  
  if(bHighlight)
  {
   fInclude("String.HighlightEngine"true);
   
   PVar.Interval = 
    setInterval
    ( 
     function()
     {
      defaultStatus = "Loading..."+(PVar.Count++);
      if(window["HighlightEngine"])
      {
       while(iCmdArCount<CmdArLen)
       {
        var sFilePath = fSetHelpPath(CmdAr[iCmdArCount]).join("");
        fXhExt(sFilePath, fHelpCallback, [bHighlight]);      
        iCmdArCount++;
        
        clearInterval(PVar.Interval);
       } // end while
       
       defaultStatus = "Done.";
       PVar.Count = 0;
      }
     }
     ,
     Param.HIntervalMs
    );
  }
  else
  {
   while(iCmdArCount<CmdArLen)
   {
    var sFilePath = fSetHelpPath(CmdAr[iCmdArCount]).join("");
    fXhExt(sFilePath, fHelpCallback, [bHighlight]);
    iCmdArCount++;
   } // end while
  } // end if
 } // end function fHelp(sCmdList, bHighlight)
 
 function fSetHelpPath(sCmd)
 { // shawl.qiu code, return array
  var sPath = sCmd.replace(/\./g, "/");
  var sClass = sCmd.replace(/^.*\./g, "").replace(/[\d\_\-]+$/"");
  if(/^Readme$/i.test(sCmd))
  {
   return [Param.Path, "Readme", Param.HExt];
  }
  else if(/^Call$/i.test(sCmd))
  {
   return [Param.Path, "Default", Param.HExt];
  }
  else if(/^Source$/i.test(sCmd))
  {
   return [Param.Path, "default", Param.Ext];
  }
  else
  {
   //alert([Param.Path, sPath, "/", Param.HFolder, "/", sClass, Param.HExt])
   return [Param.Path, sPath, "/", Param.HFolder, "/", sClass, Param.HExt];
  }
 } // end function fSetHelpPath(sCmd)
 
 function fHelpCallback(TextAr, bHighlight)
 { // shalw.qiu code, void return;
  //alert(TextAr)
  var Body = document.body;
  
  var SpanEle = $("Span");
  
  if(bHighlight)
  {
   var Hl = new HighlightEngine();
   Hl.Go(TextAr, "Tag");
   delete Hl;
   TextAr.push("<hr/>");
   SpanEle.innerHTML = TextAr.join("");
  }
  else 
  {
   SpanEle.innerHTML = ["<xmp>", TextAr, "<\/xmp><hr/>"].join("");
  }
  
  if(Body.childNodes.length===0)
  {
   alert(0)
  }
  else
  {
   Body.insertBefore(SpanEle, Body.firstChild)
  }
 } // end function fHelpCallback(TextAr)
 
 function fIsFunc(Func)
 { // shawl.qiu code, return Boolean
  if(Func) if(Func.constructor==Function) return true;
  return false;
 } // end function fIsFunc(Func)
 
 function fXhExt(sUrl, oFunc, ExtArgAr, sMethod)
 {//shawl.qiu code, void return
  if(!sMethod) sMethod = "GET";
  var xh;
  
  try{ xh = new XMLHttpRequest();} 
  catch(e)
  {
   try{ xh = new ActiveXObject('microsoft.xmlhttp');} 
   catch(e)
   {
    try{ xh = new ActiveXObject("Msxml2.XMLHTTP");} catch(e){} // end try 2
   } // end try 1
  } // end try
  xh.open(sMethod, sUrl);
  xh.onreadystatechange =
   function()
   {
    if(xh.readyState == 4 && xh.status == 200)
    {
     if(oFunc)
     {
      if(ExtArgAr)
      {
       if(ExtArgAr.constructor==Array)
       {
        ExtArgAr.unshift([xh.responseText]);
        oFunc.apply(null, ExtArgAr);
       }
       else oFunc([xh.responseText]);
      }
      else oFunc([xh.responseText]);
     } 
     else alert(xh.responseText);
    }
   };
  
  xh.send(null);
 } // end function fXhExt(sUrl, oFunc, ExtArgAr, sMethod)

 function $(sTag){return document.createElement(sTag);}
 function _(sText){return document.createTextNode(sText);}
 
 function fGetAu(){ return Au; }
 //------------------------------------end private method
} // shawl.qiu code
//---------------------------------end class Importer()---------------------------------//
/*</script> */


5. 库类调用参考

<script type='text/javascript' src='/SqCsJsLib/default.js'></script>
<script type="text/javascript">
//<![CDATA[
 //Im.Include("ExampleNs.ExampleClass", true);
 //Im.Help("ExampleNs.ExampleClass", true);
//]]>
</script>
<script type="text/javascript">
//<![CDATA[

//]]>
</script>


6. 库类调用结构及优先顺序说明

库类调用分为三个脚本块:
一为初始库,
二为导入类,
三为初始及使用类.

@suches
http://btbtd.com/mods/blog/item.php?uid=1&item=3742

发表于 @ 2007-11-29 08:13:59

该文章暂时没有回复
评论内容:
昵称:
验证码: