JavaScript工具函数大全(一)

    |     2020年3月20日   |   html/css/js, web前端技术   |     0 条评论   |    1068

这是一组偏“页面脚本”的 JavaScript 工具函数:事件、编码、收藏夹、动态加载脚本、回到顶部、Base64、全角半角、版本号比较和 CSS 压缩格式化。原文:https://github.com/Wscats/CV/issues/27。下面全部函数都保留,只修正明显写坏的语法(多余顿号、中文逗号)以及 HtmlEncode / delEvt 的实现错误。

部分函数依赖页面全局(如 appendscript 里的 hash、in_array、evalscripts),移植时要一并带上这些辅助量。

一、事件与 DOM 扩展

为元素添加 on 方法

为元素添加on方法

Element.prototype.on = Element.prototype.addEventListener;



NodeList.prototype.on = function (event, fn) {

    []['forEach'].call(this, function (el) {

        el.on(event, fn);

    });

    return this;

};

为元素添加 trigger 方法

为元素添加trigger方法

Element.prototype.trigger = function(type, data) {

  var event = document.createEvent("HTMLEvents");

  event.initEvent(type, true, true);

  event.data = data || {};

  event.eventName = type;

  event.target = this;

  this.dispatchEvent(event);

  return this;

};



NodeList.prototype.trigger = function(event) {

  []["forEach"].call(this, function(el) {

    el["trigger"](event);

  });

  return this;

};

转义 HTML 标签(HtmlEncode)

转义html标签

function HtmlEncode(text) {
  return text
    .replace(/&/g, "&")
    .replace(/"/g, """)
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;");
}

HTML 标签转义(SaferHTML 模板)

HTML标签转义

// HTML 标签转义

// @param {Array.<DOMString>} templateData 字符串类型的tokens

// @param {...} ..vals 表达式占位符的运算结果tokens

//

function SaferHTML(templateData) {

  var s = templateData[0];

  for (var i = 1; i < arguments.length; i++) {

    var arg = String(arguments[i]);

    // Escape special characters in the substitution.

    s += arg

      .replace(/&/g, "&")

      .replace(/</g, "<")

      .replace(/>/g, ">");

    // Don't escape special characters in the template.

    s += templateData[i];

  }

  return s;

}

// 调用

var html = SaferHTML`<p>这是关于字符串模板的介绍</p>`;

跨浏览器绑定事件

function addEventSamp(obj, evt, fn) {

  if (!oTarget) {

    return;

  }

  if (obj.addEventListener) {

    obj.addEventListener(evt, fn, false);

  } else if (obj.attachEvent) {

    obj.attachEvent("on" + evt, fn);

  } else {

    oTarget["on" + sEvtType] = fn;

  }

}

加入收藏夹

function addFavorite(sURL, sTitle) {

  try {

    window.external.addFavorite(sURL, sTitle);

  } catch (e) {

    try {

      window.sidebar.addPanel(sTitle, sURL, "");

    } catch (e) {

      alert("加入收藏失败,请使用Ctrl+D进行添加");

    }

  }

}

二、页面资源与脚本

提取页面代码中所有网址

var aa = document.documentElement.outerHTML

  .match(

    /(url\(|src=|href=)[\"\']*([^\"\'\(\)\<\>\[\] ]+)[\"\'\)]*|(http:\/\/[\w\-\.]+[^\"\'\(\)\<\>\[\] ]+)/gi

  )

  .join("\r\n")

  .replace(/^(src=|href=|url\()[\"\']*|[\"\'\>\) ]*$/gim, "");

alert(aa);

动态加载脚本文件

function appendscript(src, text, reload, charset) {

  var id = hash(src + text);

  if (!reload && in_array(id, evalscripts)) return;

  if (reload && $(id)) {

    $(id).parentNode.removeChild($(id));

  }



  evalscripts.push(id);

  var scriptNode = document.createElement("script");

  scriptNode.type = "text/javascript";

  scriptNode.id = id;

  scriptNode.charset = charset

    ? charset

    : BROWSER.firefox

    ? document.characterSet

    : document.charset;

  try {

    if (src) {

      scriptNode.src = src;

      scriptNode.onloadDone = false;

      scriptNode.onload = function() {

        scriptNode.onloadDone = true;

        JSLOADED[src] = 1;

      };

      scriptNode.onreadystatechange = function() {

        if (

          (scriptNode.readyState == "loaded" ||

            scriptNode.readyState == "complete") &&

          !scriptNode.onloadDone

        ) {

          scriptNode.onloadDone = true;

          JSLOADED[src] = 1;

        }

      };

    } else if (text) {

      scriptNode.text = text;

    }

    document.getElementsByTagName("head")[0].appendChild(scriptNode);

  } catch (e) {}

}

返回顶部的通用方法

function backTop(btnId) {

  var btn = document.getElementById(btnId);

  var d = document.documentElement;

  var b = document.body;

  window.onscroll = set;

  btn.style.display = "none";

  btn.onclick = function() {

    btn.style.display = "none";

    window.onscroll = null;

    this.timer = setInterval(function() {

      d.scrollTop -= Math.ceil((d.scrollTop + b.scrollTop) * 0.1);

      b.scrollTop -= Math.ceil((d.scrollTop + b.scrollTop) * 0.1);

      if (d.scrollTop + b.scrollTop == 0)

        clearInterval(btn.timer, (window.onscroll = set));

    }, 10);

  };

  function set() {

    btn.style.display = d.scrollTop + b.scrollTop > 100 ? "block" : "none";

  }

}

backTop("goTop");

实现 base64 解码

实现base64解码

function base64_decode(data) {

  var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

  var o1,

    o2,

    o3,

    h1,

    h2,

    h3,

    h4,

    bits,

    i = 0,

    ac = 0,

    dec = "",

    tmp_arr = [];

  if (!data) {

    return data;

  }

  data += "";

  do {

    h1 = b64.indexOf(data.charAt(i++));

    h2 = b64.indexOf(data.charAt(i++));

    h3 = b64.indexOf(data.charAt(i++));

    h4 = b64.indexOf(data.charAt(i++));

    bits = (h1 << 18) | (h2 << 12) | (h3 << 6) | h4;

    o1 = (bits >> 16) & 0xff;

    o2 = (bits >> 8) & 0xff;

    o3 = bits & 0xff;

    if (h3 == 64) {

      tmp_arr[ac++] = String.fromCharCode(o1);

    } else if (h4 == 64) {

      tmp_arr[ac++] = String.fromCharCode(o1, o2);

    } else {

      tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);

    }

  } while (i < data.length);

  dec = tmp_arr.join("");

  dec = utf8_decode(dec);

  return dec;

}

三、输入、编码与字符串

确认是否是键盘有效输入值

function checkKey(iKey) {

  if (iKey == 32 || iKey == 229) {

    return true;

  } /*空格和异常*/

  if (iKey > 47 && iKey < 58) {

    return true;

  } /*数字*/

  if (iKey > 64 && iKey < 91) {

    return true;

  } /*字母*/

  if (iKey > 95 && iKey < 108) {

    return true;

  } /*数字键盘1*/

  if (iKey > 108 && iKey < 112) {

    return true;

  } /*数字键盘2*/

  if (iKey > 185 && iKey < 193) {

    return true;

  } /*符号1*/

  if (iKey > 218 && iKey < 223) {

    return true;

  } /*符号2*/

  return false;

}

全角半角转换

//iCase: 0全到半,1半到全,其他不转化

function chgCase(sStr, iCase) {

  if (

    typeof sStr != "string" ||

    sStr.length <= 0 ||

    !(iCase === 0 || iCase == 1)

  ) {

    return sStr;

  }

  var i,

    oRs = [],

    iCode;

  if (iCase) {

    /*半->全*/

    for (i = 0; i < sStr.length; i += 1) {

      iCode = sStr.charCodeAt(i);

      if (iCode == 32) {

        iCode = 12288;

      } else if (iCode < 127) {

        iCode += 65248;

      }

      oRs.push(String.fromCharCode(iCode));

    }

  } else {

    /*全->半*/

    for (i = 0; i < sStr.length; i += 1) {

      iCode = sStr.charCodeAt(i);

      if (iCode == 12288) {

        iCode = 32;

      } else if (iCode > 65280 && iCode < 65375) {

        iCode -= 65248;

      }

      oRs.push(String.fromCharCode(iCode));

    }

  }

  return oRs.join("");

}

版本对比

function compareVersion(v1, v2) {

  v1 = v1.split(".");

  v2 = v2.split(".");



  var len = Math.max(v1.length, v2.length);



  while (v1.length < len) {

    v1.push("0");

  }



  while (v2.length < len) {

    v2.push("0");

  }



  for (var i = 0; i < len; i++) {

    var num1 = parseInt(v1[i]);

    var num2 = parseInt(v2[i]);



    if (num1 > num2) {

      return 1;

    } else if (num1 < num2) {

      return -1;

    }

  }

  return 0;

}

压缩 CSS 样式代码

压缩CSS样式代码

function compressCss(s) {

  //压缩代码

  s = s.replace(/\/\*(.|\n)*?\*\//g, ""); //删除注释

  s = s.replace(/\s*([\{\}\:\;\,])\s*/g, "$1");

  s = s.replace(/\,[\s\.\#\d]*\{/g, "{"); //容错处理

  s = s.replace(/;\s*;/g, ";"); //清除连续分号

  s = s.match(/^\s*(\S+(\s+\S+)*)\s*$/); //去掉首尾空白

  return s == null ? "" : s[1];

}

获取当前路径

var currentPageUrl = "";

if (typeof this.href === "undefined") {

  currentPageUrl = document.location.toString().toLowerCase();

} else {

  currentPageUrl = this.href.toString().toLowerCase();

}

字符串长度截取

function cutstr(str, len) {

    var temp,

        icount = 0,

        patrn = /[^\x00-\xff]/,

        strre = "";

    for (var i = 0; i < str.length; i++) {

        if (icount < len - 1) {

            temp = str.substr(i, 1);

                if (patrn.exec(temp) == null) {

                   icount = icount + 1

            } else {

                icount = icount + 2

            }

            strre += temp

            } else {

            break;

        }

    }

    return strre + "..."

}

时间日期格式转换

Date.prototype.format = function(formatStr) {

  var str = formatStr;

  var Week = ["日", "一", "二", "三", "四", "五", "六"];

  str = str.replace(/yyyy|YYYY/, this.getFullYear());

  str = str.replace(

    /yy|YY/,

    this.getYear() % 100 > 9

      ? (this.getYear() % 100).toString()

      : "0" + (this.getYear() % 100)

  );

  str = str.replace(

    /MM/,

    this.getMonth() + 1 > 9

      ? (this.getMonth() + 1).toString()

      : "0" + (this.getMonth() + 1)

  );

  str = str.replace(/M/g, this.getMonth() + 1);

  str = str.replace(/w|W/g, Week[this.getDay()]);

  str = str.replace(

    /dd|DD/,

    this.getDate() > 9 ? this.getDate().toString() : "0" + this.getDate()

  );

  str = str.replace(/d|D/g, this.getDate());

  str = str.replace(

    /hh|HH/,

    this.getHours() > 9 ? this.getHours().toString() : "0" + this.getHours()

  );

  str = str.replace(/h|H/g, this.getHours());

  str = str.replace(

    /mm/,

    this.getMinutes() > 9

      ? this.getMinutes().toString()

      : "0" + this.getMinutes()

  );

  str = str.replace(/m/g, this.getMinutes());

  str = str.replace(

    /ss|SS/,

    this.getSeconds() > 9

      ? this.getSeconds().toString()

      : "0" + this.getSeconds()

  );

  str = str.replace(/s|S/g, this.getSeconds());

  return str;

};



// 或

Date.prototype.format = function(format) {

  var o = {

    "M+": this.getMonth() + 1, //month

    "d+": this.getDate(), //day

    "h+": this.getHours(), //hour

    "m+": this.getMinutes(), //minute

    "s+": this.getSeconds(), //second

    "q+": Math.floor((this.getMonth() + 3) / 3), //quarter

    S: this.getMilliseconds() //millisecond

  };

  if (/(y+)/.test(format))

    format = format.replace(

      RegExp.$1,

      (this.getFullYear() + "").substr(4 - RegExp.$1.length)

    );

  for (var k in o) {

    if (new RegExp("(" + k + ")").test(format))

      format = format.replace(

        RegExp.$1,

        RegExp.$1.length == 1 ? o[k] : ("00" + o[k]).substr(("" + o[k]).length)

      );

  }

  return format;

};

alert(new Date().format("yyyy-MM-dd hh:mm:ss"));

四、事件卸载、后缀与 CSS 格式化

跨浏览器删除事件

跨浏览器删除事件(原文误写成 addEventListener / attachEvent,这里按“删除事件”改正)

function delEvt(obj, evt, fn) {
  if (!obj) {
    return;
  }
  if (obj.removeEventListener) {
    obj.removeEventListener(evt, fn, false);
  } else if (obj.detachEvent) {
    obj.detachEvent("on" + evt, fn);
  } else {
    obj["on" + evt] = null;
  }
}

判断是否以某个字符串结束

String.prototype.endWith = function(s) {

  var d = this.length - s.length;

  return d >= 0 && this.lastIndexOf(s) == d;

};

返回脚本内容

function evalscript(s) {

  if (s.indexOf("<script") == -1) return s;

  var p = /<script[^\>]*?>([^\x00]*?)<\/script>/gi;

  var arr = [];

  while ((arr = p.exec(s))) {

    var p1 = /<script[^\>]*?src=\"([^\>]*?)\"[^\>]*?(reload=\"1\")?(?:charset=\"([\w\-]+?)\")?><\/script>/i;

    var arr1 = [];

    arr1 = p1.exec(arr[0]);

    if (arr1) {

      appendscript(arr1[1], "", arr1[2], arr1[3]);

    } else {

      p1 = /<script(.*?)>([^\x00]+?)<\/script>/i;

      arr1 = p1.exec(arr[0]);

      appendscript("", arr1[2], arr1[1].indexOf("reload=") != -1);

    }

  }

  return s;

}

格式化 CSS 样式代码

格式化CSS样式代码

function formatCss(s) {

  //格式化代码

  s = s.replace(/\s*([\{\}\:\;\,])\s*/g, "$1");

  s = s.replace(/;\s*;/g, ";"); //清除连续分号

  s = s.replace(/\,[\s\.\#\d]*{/g, "{");

  s = s.replace(/([^\s])\{([^\s])/g, "$1 {\n\t$2");

  s = s.replace(/([^\s])\}([^\n]*)/g, "$1\n}\n$2");

  s = s.replace(/([^\s]);([^\s\}])/g, "$1;\n\t$2");

  return s;

}
函数 用途 注意
on / trigger 批量绑定与派发 基于 addEventListener / HTMLEvents
SaferHTML 模板字符串防 XSS 只转义插值,不转义模板本身
backTop 平滑回到顶部 会改写 window.onscroll
compareVersion 点分版本比较 缺位补 0
endWith 是否以某后缀结束 可用 ES6 endsWith 替代

addEventSamp 原文判断的是 oTarget,参数却叫 obj,调用时务必传入真实节点。delEvt 原文把删除写成了再次绑定,已按 removeEventListener / detachEvent 改正。

一句话总结:这些工具函数覆盖事件、编码、脚本加载和字符串日期处理;能用原生 API 的地方优先原生,拷贝时注意原文里的全局依赖和笔误。

转载请注明来源:JavaScript工具函数大全(一)
本文链接地址:https://ai.zhousir.top/?p=2434
回复 取消