关于懒狗开始记笔记的备注
在协助调试修改的过程中,某些兼容性问题不记录真的愧对摸鱼仔的称呼
文章目录
一、區分ios & Android 環境
function initForPhone() {
var userAgent = navigator.userAgent.toLowerCase();
var deviceBrand = "";
var osVersion = "";
// Judge whether to is ios device
if (/iphone|ipod|ipad/i.test(userAgent)) {
deviceBrand = "Apple";
// Get the ios version
var noarmalOs = userAgent.match(/os (\d+)[._](\d+)[._](\d+)?/);
if (null != noarmalOs) {
osVersion =
noarmalOs[1] + "." + noarmalOs[2] + "." + (noarmalOs[3] || 0);
} else {
//for ipad and ipad mini
osVersion = userAgent.match(
/\(ipad;\s[\w.]+\s[0-9_.a-z]+\s([0-9_]+)[\w\s]+\)/i
)[1];
deviceBrand = "ipad";
}
// Judge whether to is Andrioid device
} else if (/android/i.test(userAgent)) {
try {
let normalBrand = userAgent.match(/(zh-cn;)?([\w\s-]+)\sbuild/i);
if (null == normalBrand) {
//For more advanced mobile phones
deviceBrand = userAgent.match(/\(linux;[\s\w.]+;\s([\w-\s]+)\)/i)[1];
} else {
deviceBrand = normalBrand[2];
}
osVersion = userAgent.match(/android\s([0-9\.]*)/)[1];
} catch (e) {
deviceBrand = "android";
}
}
let config = {}
config.model = deviceBrand;
config.osVersion = osVersion;
return config;
}
A、ios兼容性问题
1、 ios15 系列(网址栏下移问题)
ios15以及ios15.1新版优化,网址展示端移至最下端,约为
52px
2、ios web端自动放大问题(点击输入框)
找meta方法,基本都是浪费时间,建议直接font-size 大于或等于16即可。
B、 Android兼容性问题
1、replaceAll not a function
是关于部分手机的webview 采用的内核版本过低的问题
String.prototype.replaceAll = function (search, replacement) {
let target = this;
return target.replace(new RegExp(search, 'g'), replacement);
};
三、无障碍兼容性问题
1、焦点问题(不按照tabindex移动)
采用手工管理的方式,控制所有需要流动的焦点
整体思路
:
①整理所有需要按需移动的元素
②监听需要截取的元素区域,切换至上一个或下一个时,为其手动匹配聚焦元素(同时忽略掉默认事件)
①初始化方法
使得所有需要监听的元素就位,初始化初始与结束节点,保证循环聚焦且不干扰区域外的聚焦动作
··· 预设全局参数···
//原有焦點(初始焦点)
var focusedElementBeforeModal;
//元素集合(若监听的元素为可增加,通常为变动的)
var focusElement = [];
//需要监听的元素选择器
var focusElementString = "div.cont,.chat-txt a";
//最开始的元素
var firstTabStart;
//最后的一个元素(若监听的元素为可增加,通常为变动的)
var lastTabStop;
//需要监听的内容外框,也就是只会监听这个元素下的内容焦点变化
var listenWindowSelector = ".chat-window";
··· 预设全局参数结束···
/**
*@todo 初始化方法,获取当前存在的元素
*/
function focuslistens() {
focusmodal = document.querySelector(listenWindowSelector);
//初始化当前焦点状态
focusedElementBeforeModal = document.activeElement;
focusmodal.addEventListener("keydown", trapTabKey);
//获取
focusElement = focusmodal.querySelectorAll(focusElementString)
//初始化最开始的元素内容
firstTabStart = focusElement[0];
//更新最后一个元素的内容
lastTabStop = focusElement[focusElement.length - 1];
//需要监听的元素
let listenWindow = $(".chat-window")[0];
//焦点监听方法
function trapTabKey(e) {
//监听Tab键输入 ,同时判断是否处于监听内容之内
if (e.keyCode === 9 && e.path.includes(listenWindow)) {
// SHIFT + TAB
if (e.shiftKey) {
//滑动至最后一个时,更新到最开始的元素
if (document.activeElement === firstTabStart) {
e.preventDefault();
lastTabStop.focus();
}
// TAB
} else {
if (document.activeElement === lastTabStop) {
e.preventDefault();
firstTabStart.focus();
}
}
}
}
}
②更新元素方法
实际上元素总是动态增加的,固定的不常有,因此补充动态监听,放置在会触发更新元素的方法后即可。
function upgradeELement() {
//重新获取元素内容,避免元素删除或增加导致聚焦点不符合预期
focusElement = focusmodal.querySelectorAll(focusElementString)
//更新末尾焦点
lastTabStop = focusElement[focusElement.length - 1];
//更新首位焦点(通常不会出现首位焦点变动,为保障,还是保留)
firstTabStart = focusElement[0];
}
四、pc瀏覽器兼容性問題
1、第三方cookies即将退出历史舞台的问题
针对这个问题,通常只会
影响嵌入的网站
,若为自己的网站可以略过。
具体表现为: 浏览器会默认禁止第三方获取cookies内容。
等同于: 为cookies增加了httpOnly
①避免报错情况
利用自定义属性来避免调用到禁止第三方设置的浏览器爆出异常,无法运行。
但无法替代正常cookies来存储信息,相当于本地变量
try {
storage.item = window.localStorage
} catch (e) {
//unsupport thrid cookies
storage = {
map: {},
clean: function () {
storage.map = {};
},
setItem: function (key, val) {
storage.map[key] = val;
},
getItem: function (key) {
let restult = storage.map[key];
if (undefined == restult) {
return null;
} else {
return restult;
}
}
}
}
②间接与主站操作cookies
可以采用如
HTML自带postMessage
处理:
可以不担心针对跨域问题,只需要有页面父子嵌套
关系即可
整体使用两个方法:
一、
postMessage
:
①param1
:传输内容,可以任意格式,当然建议结构化的数据
②param2
:iframe所绑定的url(协议、主机地址或端口三者匹配才可),当然也可以使用*
匹配任意origin,但是不安全所以不推荐。(摸鱼不要太过分)
————————————————
二、window.addEventListener
①param1
:监听这个事件,只能使用message
②param2
:
data
从其他 window 中传递过来的对象。origin
调用 postMessage 时消息发送方窗口的 origin .可以简单认为是urlsource
对发送消息的窗口对象的引用,如果是iframe可以不需要使用
示例如下,父子页面为嵌套iframe模式
父页面
// 设嵌套的iframe 对应id为 demo
// 获取对象
var demoIframe = document.getElementById('demo');
var url = 'https://coffeeandice.cn';
function judge(event){
let origin = event.origin;
if(origin == window.location.origin){
ifr.contentWindow.postMessage("连接好了", url );
}else{
ifr.contentWindow.postMessage("不是需要连接的origin", url );
}
}
··· 初始化内容···
// 参数一:可以自定义数值
// 参数二:对应要传输消息的iframe绑定的url,也就是 demoIframe 对应的url
ifr.contentWindow.postMessage("{'type':'1','content':'hi','id':'ringo'}", url );
window.addEventListener('message',judge)
··· 初始化结束···
子页面
function judge(event){
let origin = event.origin;
if(origin == window.location.origin){
//这里是top直接可以引用父页面
//若非引用,则可以使用event.source
top.contentWindow.postMessage("连接好了", url );
}else{
//完全不回应
}
}
··· 初始化内容···
window.addEventListener('message',judge)
··· 初始化结束···
五、脚本工具兼容性问题
1、jquery.autocomplete(自动补全)(缺少节流)
本人主要是使用 14.10版本
由于某些版本浏览器样式或功能有冲突导致无法展示,所以懒狗还是自己求自己。
节流功能
:记得再补充
懒狗思路:
整体上采取倒序匹配的方式来匹配答案,利用全局变量避免重复请求的问题
主要分为以下注意点:
①全量匹配模式
②分段匹配模式
(1)从输入内容后面开始裁剪
(2)分段模式下但凡长度不为零都可裁减匹配
③匹配值存储
④避免拼音干扰
简单实现:
数据源
[
"你好呀",
"你好呀,吃饭没",
"你妈叫你吃饭",
"你爸叫你回家吃饭"
]
//定义最小匹配长度
let minLimit = 2;
/*
*@todo 利用类map来收集存储数据,整体结构为k-array
* eg: {'你好',["你好呀",”你好呀,吃饭没“]}
*/
let smartTipsGather ={};
/**
* @todo 定义处理方法
* @return 返回匹配值
*/
smartTipsMatchHandler(input=>{
//精准匹配内容
let accurateAnswer = "";
//检测本地变量种是否存在内容
let dataGather = smartTipsGather;
//匹配的内容
let matchAnswer = "";
//截取后待匹配的值
let vague = input;
//@todo 精准匹配,顾名思义全量匹配
accurateAnswer = dataGather[input];
/**
* @todo 分段匹配模式(取决实际,一般为前缀)
* 其实这里有很多玩法,各种匹配方式很爽
**/
if (!(Array.isArray(accurateAnswer))) {
//初始化截断匹配答案
let vagueAnswer = "";
//判断可截断长度
let vagueLastIndex = param.length;
//当未匹配且还可继续截断时,继续进入下一个循环
while (!rematch(vague) && vague.length > minLimit) {
if (!rematch(vague)) {
//截取提问,进入下一个循环
vague = param.substring(0, vagueLastIndex--);
}
}
//当匹配成功,返回数据
vagueAnswer = rematch(vague);
if (vagueAnswer.length > 0) {
matchAnswer = vagueAnswer;
}
} else {
matchAnswer = accurateAnswer;
}
/**
* @todo 反向匹配
*/
function rematch(vague) {
let vagueAnswer = "";
for (let op in dataGather) {
if (vague.indexOf(op) != -1) {
vagueAnswer = op;
break;
}
}
return vagueAnswer;
};
/**
* @todo network support
* 判断匹配的值是否为数组,不为则没有匹配上
*/
if (!(Array.isArray(matchAnswer))) {
//本方法参照一般http请求即可(promise)
smartTipsHandler(param).then(res => {
let data = res.data;
if (data) {
matchAnswer = data;
smartTipsGather[param] = data;
} else {
//赋值默认为空值
matchAnswer = []
smartTipsGather[param] = [];
}
return matchAnswer;
}.fail(error=>{
//赋值默认为空值
smartTipsGather[param] = [];
return [];
})
} else {
return matchAnswer;
}
})
避免拼音干扰:
/**
* @todo listen the event of pinyin
* @type {boolean}
*/
//默认输入框id值:textArea
//判断是否输入
var inputDoing = false;
//开始输入
document.getElementById('textArea').addEventListener('compositionstart', function (e) {inputDoing = true;}, false);
//输入中
document.getElementById('textArea').addEventListener('input', function (e) {if (!inputDoing){smartTipsMatchHandler(document.getElementById("textArea").innerText);
}}, false);
//输入结束
document.getElementById('textArea').addEventListener('compositionend', function (e) {
inputDoing = false;
smartTipsMatchHandler(document.getElementById("textArea").innerText);
}, false);