// 这里提供给HTML DOM对象迭代的简化写法
// 原本写({obj:oMyHtmlDom}).each(...)的,现在写J(oMyHtmlDom).each(...)就可以了
// 这里出现后将移进Jcore.js里,以后使用的地方将不再说明
// 使用举例
/*
// 'myTestDiv'.XPath()[0]其实也可以字节用'myTestDiv'就可以了
J('myTestDiv'.XPath()[0]).each(function()
{
  // 如果有属性value就赋予其值, 注意,后面的( )使必须的,因为逻辑运算符号优先于赋值符号
  'value' in this && (this.value = 'good');
}, true);
*/
var J = Object.prototype.J = function(o)
{
  // 直接传递一个函数参数,就认为是要在页面加载完后执行
  if("function" == typeof o)
  {
     fnAddEvent(window, "onload", o);
     return this;
  }
  // 如果你希望设置回调函数的方式来处理XPath的结果,
  // 可以在第二个参数设置回调函数,
  // 回调函数的入口参数、上下文this就是XPath选择的结果
  if(1 < arguments.length && Function == arguments[1].constructor)
  {
     var oCbkFunc = arguments[1];
     fnRegCbkFun(function()
     {
       var a = J(o);
       oCbkFunc.call(a, a);
       delete a;
     }, arguments[2] || 13);
     return [];
  }
  var nCount = 0, szT;
  // new XPath(o)的形式就兼容了传入id,nodeName或Xpath的 情况
  o = String == o.constructor ? (Array == this.constructor ? this.XPath(o) : new XPath(o)) : _A(o);
  // 支持动态的这样的行为设计的好处是功能强大,不随浏览器的升级而不支持
  // 缺点是每次都需要对每个对象进行for in处理,效率会受到影响
  // 所以我们以IE为标准,以53个事件为最大值来处理
  // 如果你把下面注释的代码注释打开,那么就支持上面描述的功能
  // 如果你不打开,我们已经在本代码的后面部分用静态的方式支持了
  return o/*.each(function()
  {
    // 动态支持绑定N个事件的设计,即使是浏览器升级后有新的事件类型也支持
    for(var k in this)
     if(0 == k.indexOf("on"))
     {
        if(nCount >= 53)throw {message:"避免性能问题",jname:"J"};
        szT = k.substr(2);
        // !!!就是将变量转换为Boolean,判断他是不是“不”为真
        if(!o[szT])
        {
           nCount++;if('click' == szT)alert("J: " + szT)
           // 这样就支持J('myTest')['click'](function(){}) ... J('myTest')['change'](function(){})这样的方法了
           o[szT] = (function(func)
           {
              // 这里提取出来的目的是下面的迭代器里将要用到他
              var szTp = this.type;
              // 迭代所有元素,都绑定func行为响应函数
              return this._this.each(function(a,i)
              {
                 fnAddEvent(this, szTp, func);
              });
              delete szTp;
           // 这里将当前的对象和HTML对象以及绑定行为的事件名一起bind进去,好便于操作
           }).bind({_this:o, obj:this, type:k});
        }
     }
  })*/;
};
// 功能描述:注意,这里只是模拟多线程的运行,但是并不能真正的提高执行效率
// o是Object对象或function对象,成员有:
// clbkMsg: 执行完后返回的消息
// clbkObj: 需要将clbkMsg填写到HTML对象clbkObj上的value或innerHTML上
// clbkFun: 回调函数,必须只是处理循环中单轮的动作,比如你要启动多线程来清空
//          一个表格你的数据,保留原有的风格,那么你的clbkFun就只能处理单行、
//          列的数据,而处理哪行,则fnCreateMThread会给你传递进来;
//          如果不是不是循环,只是单个函数的非阻塞处理,
//          返回true就继续调用clbkFunc函数,否则就退出这样的
//          类似循环的调用,因此请注意你的回调函数的返回值,以防止死循环,
//          这时候的clbkFun没有任何入口参数
// ovFun  : 执行完所有的循环、clbkFun后调用的函数,这样就比clbkMsg、clbkObj这两个参数更加灵活了
// nStart : 循环开始的数字,默认从0开始
// nEnd   : 循环结束的数字
// nThrdNm: 开启的线程数,默认是每5个单轮处理一个线程
// nTime  : 每次执行的间隔时间,默认是1毫秒,间隔时间越长,这操作界面就越流畅,不阻塞
// 如果传入的是function对象而没有任何的成员,那么就启动无阻塞的模式执行他
// 返回信息:返回当前对象
// 使用指南:
// 应用范围:各种Web客户端和服务端开发
function fnCreateMThread(o)
{
   // 以对象方式允许,以便得到更优越的性能
   if(window == this)
     return new fnCreateMThread(o);//????为什么性能更加优越
   // 同样,这里防止下面使用无效的o这个对象
   o || (o = {});//???这边的逻辑是什么意思
   o.nTime || (o.nTime = 13);
   // 如果不是单纯的函数非阻塞运行??什么叫做非阻塞
   if(o.nEnd && o.clbkFun)
   {
      // 默认从0开始,如果你没有设置他
      o.nStart  || (o.nStart = 0);
      // 每个线程处理的次数
      this.nL = 5;
      // 线程执行完成数
      this.nOvThrd = 0;
      var n = o.nEnd - o.nStart, k, _this = this;
      // 求每个线程需要处理的区段的次数
      // 下面,以逗号运算符号,减少{ }中的一个字符的字节数
      if(o.nThrdNm)
           k = n % o.nThrdNm,
           this.nL = (n - k) / o.nThrdNm + (0 < k ? 1 : 0);
      else k = n % this.nL,
           o.nThrdNm = (n - k) / this.nL + (0 < k ? 1 : 0);
      // timer计数器
      this.m_arrTmer = [];
      // 启动多线程
      for(var i = o.nStart; i < o.nEnd; i += this.nL)
      {
         this.nOvThrd++;
         this.m_arrTmer.push(window.setInterval(function()
         {//这边push是用来干嘛的push参数怎么可以是一个这么复杂的调用函数           if(this.nfEnd > this.nfStart)
           {
             // J("#myIpt" + this.pos)[0].value = [this.pos, this.nfEnd, this.nfStart].join(" | ");
             // 传入当前处理的序号,和当前的线程号//这边的J应该是一个
             o.clbkFun(this.nfStart++, this.pos);
           }
           else
           {
             _this.nOvThrd--;
             // 结束当前的线程
             window.clearInterval(_this.m_arrTmer[this.pos]);
             if(0 == _this.nOvThrd)
             {
                // 注意:'value' in o.clbkObj 是判断对象时候有给定的属性,这比hasOwnProperty更加通用了
                // 因为这样的方式不但支持JavaScript对象,同时也支持HTML DOM对象
                if(o.ovFun)o.ovFun();
                else
                {
                    var s = '非阻塞模式函数执行完毕';                     // 这里支持window和普通的HTML DOM对象或者输入对象
                    o.clbkObj && ('value' in o.clbkObj && (o.clbkObj.value = o.clbkMsg || s) ||
                   'innerHTML' in o.clbkObj && (o.clbkObj.innerHTML = o.clbkMsg || s) ||
                   'status' in o.clbkState && (o.clbkState.status = s) ||
                   'title' in o.clbkState && (o.clbkState.title = s) );
                }
             }
           }
         }.bind({pos:this.m_arrTmer.length, nfStart: i, nfEnd: i + this.nL}.bind(o)), o.nTime));
      }
   }
   else// 普通不是循环函数的非阻塞模式启动
   {
      // nTm: timer 计数器
      var nTm = 0, oFun = o.clbkFun || o;
      nTm = window.setInterval(function()
      {
         // 这里我们为什么要加try...catch?因为如果要执行的代码还未执行,而窗口却已经关闭,就会发生:
         // "不能执行已释放Script的代码"的错误
         try
         {
             if(!oFun())
             {
               delete oFun;
               window.clearInterval(nTm);
               // 注意:'value' in o.clbkObj 是判断对象时候有给定的属性,这比hasOwnProperty更加通用了
               // 因为这样的方式不但支持JavaScript对象,同时也支持HTML DOM对象
               if(o.ovFun)return o.ovFun();
               else
               {
                  var s = '非阻塞模式函数执行完毕';
                  o.clbkObj && ('value' in o.clbkObj && (o.clbkObj.value = o.clbkMsg || s) ||
                  'innerHTML' in o.clbkObj && (o.clbkObj.innerHTML = o.clbkMsg || s) ||
                  'status' in o.clbkState && (o.clbkState.status = s) ||
                  'title' in o.clbkState && (o.clbkState.title = s) );
               }
             }
         }catch(e){}
      }, o.nTime);
   }
   return this;
}// 功能描述:将给的function当作无阻塞模式来运行
// 返回信息:返回无
// 使用指南:fnRegCbkFun(function(){要非阻塞方式执行的代码});
// 应用范围:各种Web客户端
function fnRegCbkFun(callback, nTm)
{
  nTm || (nTm = 13);
  new fnCreateMThread({clbkFun:function()
  {
    callback();
    return false;
  },nTime:nTm});
};// 功能描述:功能强大的通用对象的绑定实现,支持function
// 这里出现后就提到"Jcore.js"里,以后章节将不在出现,而
// Jcore.js里原有的function的bind将删除,请读者注意
// 返回信息:function对象的时候返回绑定后的function对象,否则返回绑定后的对象
// 使用指南:例子代码比较多,这里就不给出使用举例了,请见下面的例子
// 应用范围:各种Web客户端和服务端开发
Object.prototype.bind = function()
{
  var a = _A(arguments), _this = this;
  switch(_this['constructor'])
  {
     // 针对Function的处理
     // 不过要特别注意的是,Function的bind是要返回一个bind以后的函数的应用的
     case Function:
       // 容错处理,防止bind的时候需要绑定NaN,undefined,null,Infinity等
       !!a[0] || (a[0] = window);
       // 克隆
       var b = _A(a);
       // 由于第一个是要绑定的对象,因此不作为下面的apply的参数,所以要移除出去
       // 由于b是克隆出来的,因此移除第一个不会影响对象a
       b.shift( );
       // 注意这里返回的是函数对象,这就是对function绑定的特点
       return function()
       {
          // b.concat(_A(arguments))是为了支持绑定返回的函数应用能再传入参数
          // 如果要调整让传入的参数在最前面,那么_A(arguments).concat(b)换过来就可以了
          // 为什么要写这两个for in,请见2.5节
          var p = _this['prototype'], obj = a[0];
          for(var k in p)
          {
            // 必须写这个if语句,否则覆盖了Object原型的方法,会导致错误
            if(p[k] != Object.prototype[k])
              obj[k] = this[k] = p[k];
          }
          p = obj['prototype'];
          for(var k in p)
            this[k] = p[k];
          // alert(arguments[0]_this)
          return _this.apply(a[0], b.concat(_A(arguments)));
       };
       break;
     // case Object:
     default:
       a.each(function()
       {
      if(!('constructor' in this))
      _this.push(this);
      else switch(this.constructor)
          {
             case Object:
                  // 注意这里的this不等于_this
                  // 他是a迭代器,迭代进来的a的每一个元素
                  for(var k in this)
                  {
                       // bind就没有必要再覆盖了
                       // 读者朋友请注意,这里常量放在前面可以防止:
                       // == 的时候少写了一个"="而很久都无法发现
                       // != 的时候少写了"!"却不轻易发现
                       // 如果是函数,并且两个函数不相同,就做Super类似的处理
                       if(this[k] != Object.prototype[k] && _this[k] != this[k])
                       {
                          if("function" == typeof _this[k] && "function" == typeof this[k] && _this[k] != this[k])
                            // 如果不bind(_this),经过多次深层的Super后就找不到当前的this了
                            this[k].Super = _this[k].bind(_this);
                          _this[k] = this[k];
                       }
                  }
                  // 读者朋友请注意:for in的方式无法枚举出:valueOf、toString、toLocaleString,这里做一个补偿
                  this['toString'].Super       = _this['toString'].bind(_this)      , _this['toString']       = this['toString'];
                  this['valueOf'].Super        =  _this['valueOf'].bind(_this)      , _this['valueOf']        = this['valueOf'];
                  this['toLocaleString'].Super = _this['toLocaleString'].bind(_this), _this['toLocaleString'] = this['toLocaleString'];
                  break;
             case Array:
                   [].push.apply(_this, this);
                  break;
             default:
                  // 注意这里的this不等于_this
                  // 他是a迭代器,迭代进来的a的每一个元素
                  [].push.apply(_this, [this]);
          }
       });
  }
  return this;
};