PageSourceSearch

https://wf.pub/js/callapp-lib_3.1.2.js

js wf.pub collected 2026-10-06 12:28:42 UTC 14,152 bytes, 412 lines download raw bytes

1(function (global, factory) {
2    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3    typeof define === 'function' && define.amd ? define(factory) :
4    (global = global || self, global.CallApp = factory());
5  }(this, (function () { 'use strict';
6  
7    function _classCallCheck(instance, Constructor) {
8      if (!(instance instanceof Constructor)) {
9        throw new TypeError("Cannot call a class as a function");
10      }
11    }
12  
13    function _defineProperties(target, props) {
14      for (var i = 0; i < props.length; i++) {
15        var descriptor = props[i];
16        descriptor.enumerable = descriptor.enumerable || false;
17        descriptor.configurable = true;
18        if ("value" in descriptor) descriptor.writable = true;
19        Object.defineProperty(target, descriptor.key, descriptor);
20      }
21    }
22  
23    function _createClass(Constructor, protoProps, staticProps) {
24      if (protoProps) _defineProperties(Constructor.prototype, protoProps);
25      if (staticProps) _defineProperties(Constructor, staticProps);
26      return Constructor;
27    }
28  
29    function _defineProperty(obj, key, value) {
30      if (key in obj) {
31        Object.defineProperty(obj, key, {
32          value: value,
33          enumerable: true,
34          configurable: true,
35          writable: true
36        });
37      } else {
38        obj[key] = value;
39      }
40  
41      return obj;
42    }
43  
44    function _extends() {
45      _extends = Object.assign || function (target) {
46        for (var i = 1; i < arguments.length; i++) {
47          var source = arguments[i];
48  
49          for (var key in source) {
50            if (Object.prototype.hasOwnProperty.call(source, key)) {
51              target[key] = source[key];
52            }
53          }
54        }
55  
56        return target;
57      };
58  
59      return _extends.apply(this, arguments);
60    }
61  
62    var ua = navigator.userAgent || ''; // 版本号比较
63  
64    var semverCompare = function semverCompare(verionA, versionB) {
65      var isNaN = Number.isNaN;
66      var splitA = verionA.split('.');
67      var splitB = versionB.split('.');
68  
69      for (var i = 0; i < 3; i++) {
70        var snippetA = Number(splitA[i]);
71        var snippetB = Number(splitB[i]);
72        if (snippetA >
72 snippetB) return 1;
73        if (snippetB > snippetA) return -1; // e.g. '1.0.0-rc' -- Number('0-rc') = NaN
74  
75        if (!isNaN(snippetA) && isNaN(snippetB)) return 1;
76        if (isNaN(snippetA) && !isNaN(snippetB)) return -1;
77      }
78  
79      return 0;
80    };
81    /**
82     * 获取 ios 大版本号
83     */
84  
85    var getIOSVersion = function getIOSVersion() {
86      var version = navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/);
87      return Number.parseInt(version[1], 10);
88    };
89    /**
90     * 获取 微信 版本号
91     */
92  
93    var getWeChatVersion = function getWeChatVersion() {
94      var version = navigator.appVersion.match(/micromessenger\/(\d+\.\d+\.\d+)/i);
95      return version[1];
96    };
97    var isAndroid = /android/i.test(ua);
98    var isIos = /iphone|ipad|ipod/i.test(ua);
99    var isWechat = /micromessenger\/([\d.]+)/i.test(ua);
100    var isWeibo = /(weibo).*weibo__([\d.]+)/i.test(ua);
101    var isBaidu = /(baiduboxapp)\/([\d.]+)/i.test(ua);
102    var isQQ = /qq\/([\d.]+)/i.test(ua);
103    var isQQBrowser = /(qqbrowser)\/([\d.]+)/i.test(ua);
104    var isQzone = /qzone\/.*_qz_([\d.]+)/i.test(ua); // 安卓 chrome 浏览器,包含 原生chrome浏览器、三星自带浏览器、360浏览器以及早期国内厂商自带浏览器
105  
106    var isOriginalChrome = /chrome\/[\d.]+ mobile safari\/[\d.]+/i.test(ua) && isA
106ndroid && ua.indexOf('Version') < 0; // chrome for ios 和 safari 的区别仅仅是将 Version/<VersionNum> 替换成了 CriOS/<ChromeRevision>
107    // ios 上很多 app 都包含 safari 标识,但它们都是以自己的 app 标识开头,而不是 Mozilla
108  
109    var isSafari = /safari\/([\d.]+)$/i.test(ua) && isIos && ua.indexOf('Crios') < 0 && ua.indexOf('Mozilla') === 0;
110  
111    // 生成基本的 url scheme
112    function buildScheme(config, options) {
113      var path = config.path,
114          param = config.param;
115      var customBuildScheme = options.buildScheme;
116  
117      if (typeof customBuildScheme !== 'undefined') {
118        return customBuildScheme(config, options);
119      }
120  
121      var _options$scheme = options.scheme,
122          host = _options$scheme.host,
123          port = _options$scheme.port,
124          protocol = _options$scheme.protocol;
125      var portPart = port ? ":".concat(port) : '';
126      var hostPort = host ? "".concat(host).concat(portPart, "/") : '';
127      var query = typeof param !== 'undefined' ? Object.keys(param).map(function (key) {
128        return "".concat(key, "=").concat(param[key]);
129      }).join('&') : '';
130      var urlQuery = query ? "?".concat(query) : '';
131      return "".concat(protocol, "://").concat(hostPort).concat(path).concat(urlQuery);
132    } // 生成业务需要的 url scheme(区分是否是外链)
133  
134    function generateScheme(config, options) {
135      var outChain = options.outChain;
136      var uri = buildScheme(config, options);
137  
138      if (typeof outChain !== 'undefined' && outChain) {
139        var protocol = outChain.protocol,
140            path = outChain.path,
141            key = outChain.key;
142        uri = "".concat(protocol, "://").concat(path, "?").concat(key, "=").concat(encodeURIComponent(uri));
143      }
144  
145      return uri;
146    } // 生成 android intent
147  
148    function generateIntent(config, options) {
149      var outChain = options.outChain;
150      var intent = options.intent,
151          fallback = options.fallback;
152      if (typeof intent === 'undefined') return '';
153      var keys = Object.keys(intent);
154      var intentParam = keys.map(function (key) {
155        return "".concat(key, "=").concat(intent[key], ";");
156      }).join('');
157      var intentTail = "#Intent;".concat(intentParam, "S.browser_fallback_url=").concat(encodeURIComponent(fallback), ";end;");
158      var urlPath = buildScheme(config, options);
159  
160      if (typeof outChain !== 'undefined' && outChain) {
161        var path = outChain.path,
162            key = outChain.key;
163        return "intent://".concat(path, "?").concat(key, "=").concat(encodeURIComponent(urlPath)).concat(intentTail);
164      }
165  
166      urlPath = urlPath.slice(urlPath.indexOf('//') + 2);
167      return "intent://".concat(urlPath).concat(intentTail);
168    } // 生成 universalLink
169  
170    function generateUniversalLink(config, options) {
171      var universal = options.universal;
172      if (typeof universal === 'undefined') return '';
173      var host = universal.host,
174          pathKey = universal.pathKey;
175      var path = config.path,
176          param = config.param;
177      var query = typeof param !== 'undefined' ? Object.keys(param).map(function (key) {
178        return "".concat(key, "=").concat(param[key]);
179      }).join('&') : '';
180      var urlQuery = query ? "&".concat(query) : '';
181      return "https://".concat(host, "?").concat(pathKey, "=").concat(path).concat(urlQuery);
182    } // 生成 应用宝链接
183  
184    function generateYingYongBao(config, options) {
185      var url = generateScheme(config, options); // 支持 AppLink
186  
187      return "".concat(options.yingyongbao, "&android_schema=").concat(encodeURIComponent(url));
188    }
189  
190    var hidden;
191    var visibilityChange;
192    var iframe;
193  
194    function getSupportedProperty() {
195      if (typeof document.hidden !== 'undefined') {
196        // Opera 12.10 and Firefox 18 and later support
197        hidden = 'hidden';
198        visibilityChange = 'visibilitychange';
199      } else if (typeof document.msHidden !== 'undefined') {
200        hidden = 'msHidden';
201        visibilityChange = 'msvisibilitychange';
202      } else if (typeof document.webkitHidden !== 'undefined') {
203        hidden = 'webkitHidden';
204        visibilityChange = 'webkitvisibilitychange';
205      }
206    }
207  
208    getSupportedProperty();
209    /**
210     * 判断页面是否隐藏(进入后台)
211     */
212  
213    function isPageHidden() {
214      if (typeof hidden === 'undefined') return false;
215      return document[hidden];
216    }
217    /**
218     * 通过 top.location.href 跳转
219     * 使用 top 是因为在 qq 中打开的页面不属于顶级页面(iframe级别)
220     * 自身 url 变更无法触动唤端操作
221     * @param {string}} [uri] - 需要打开的地址
222     */
223  
224  
225    function evokeByLocation(uri) {
226      window.top.location.href = uri;
227    }
228    /**
229     * 通过 iframe 唤起
230     * @param {string}} [uri] - 需要打开的地址
231     */
232  
233    function evokeByIFrame(uri) {
234      if (!iframe) {
235        iframe = document.createElement('iframe');
236        iframe.frameBorder = '0';
237        iframe.style.cssText = 'display:none;border:0;width:0;height:0;';
238        document.body.append(iframe);
239      }
240  
241      iframe.src = uri;
242    }
243    /**
244     * 检测是否唤端成功
245     * @param cb - 唤端失败回调函数
246     * @param timeout
247     */
248  
249    function checkOpen(cb, timeout) {
250      var timer = setTimeout(function () {
251        var pageHidden = isPageHidden();
252  
253        if (!pageHidden) {
254          cb();
255        }
256      }, timeout);
257  
258      if (typeof visibilityChange !== 'undefined') {
259        document.addEventListener(visibilityChange, function () {
260          clearTimeout(timer);
261        });
262      } else {
263        window.addEventListener('pagehide', function () {
264          clearTimeout(timer);
265        });
266      }
267    }
268  
269    var CallApp = /*#__PURE__*/function () {
270      // Create an instance of CallApp
271      function CallApp(options) {
272        _classCallCheck(this, CallApp);
273  
274        _defineProperty(this, "options", void 0);
275  
276        var defaultOptions = {
277          timeout: 2000
278        };
279        this.options = _extends(defaultOptions, options);
280      }
281      /**
282       * 注册为方法
283       * generateScheme | generateIntent | generateUniversalLink | generateYingYongBao | checkOpen
284       */
285  
286  
287      _createClass(CallApp, [{
288        key: "generateScheme",
289        value: function generateScheme$1(config) {
290          return generateScheme(config, this.options);
291        }
292      }, {
293        key: "generateIntent",
294        value: function generateIntent$1(config) {
295          return generateIntent(config, this.options);
296        }
297      }, {
298        key: "generateUniversalLink",
299        value: function generateUniversalLink$1(config) {
300          return generateUniversalLink(config, this.options);
301        }
302      }, {
303        key: "generateYingYongBao",
304        value: function generateYingYongBao$1(config) {
305          return generateYingYongBao(config, this.options);
306        }
307      }, {
308        key: "checkOpen",
309        value: function checkOpen$1(cb) {
310          return checkOpen(cb, this.options.timeout);
311        } // 唤端失败跳转 app store
312  
313      }, {
314        key: "fallToAppStore",
315        value: function fallToAppStore() {
316          var _this = this;
317  
318          this.checkOpen(function () {
319            evokeByLocation(_this.options.appstore);
320          });
321        } // 唤端失败跳转通用(下载)页
322  
323      }, {
324        key: "fallToFbUrl",
325        value: function fallToFbUrl() {
326          var _this2 = this;
327  
328          this.checkOpen(function () {
329            evokeByLocation(_this2.options.fallback);
330          });
331        } // 唤端失败调用自定义回调函数
332  
333      }, {
334        key: "fallToCustomCb",
335        value: function fallToCustomCb(callback) {
336          this.checkOpen(function () {
337            callback();
338          });
339        }
340        /**
341         * 唤起客户端
342         * 根据不同 browser 执行不同唤端策略
343         */
344  
345      }, {
346        key: "open",
347        value: function open(config) {
348          var _this$options = this.options,
349              universal = _this$options.universal,
350              appstore = _this$options.appstore,
351              logFunc = _this$options.logFunc,
352              intent = _this$options.intent;
353          var callback = config.callback;
354          var supportUniversal = typeof universal !== 'undefined';
355          var schemeURL = this.generateScheme(config);
356          var checkOpenFall;
357  
358          if (typeof logFunc !== 'undefined') {
359            logFunc();
360          }
361  
362          if (isIos) {
363            // ios qq 禁止了 scheme 和 universalLink 唤起app,安卓不受影响 - 18年12月23日
364            // ios qq 浏览器禁止了 universalLink - 2019年5月1日
365            // ios 微信自 7.0.5 版本放开了 Universal Link 的限制
366            // ios 微博禁止了 universalLink
367            if (isWechat && semverCompare(getWeChatVersion(), '7.0.5') === -1 || isQQ || isWeibo) {
368              evokeByLocation(appstore);
369            } else if (getIOSVersion() < 9) {
370              evokeByIFrame(schemeURL);
371              checkOpenFall = this.fallToAppStore;
372            } else if (!supportUniversal || isQQBrowser || isQzone) {
373              evokeByLocation(schemeURL);
374              checkOpenFall = this.fallToAppStore;
375            } else {
376              evokeByLocation(this.generateUniversalLink(config));
377            } // Android
378            // 在微信中且配置了应用宝链接
379  
380          } else if (isWechat && typeof this.options.yingyongbao !== 'undefined') {
381            evokeByLocation(this.generateYingYongBao(config));
382          } else if (isOriginalChrome) {
383            if (typeof intent !== 'undefined') {
384              evokeByLocation(this.generateIntent(config));
385            } else {
386              // scheme 在 andriod chrome 25+ 版本上iframe无法正常拉起
387              evokeByLocation(schemeURL);
388              checkOpenFall = this.fallToFbUrl;
389            }
390          } else if (isWechat || isBaidu || isQzone) {
391            evokeByLocation(this.options.fallback);
392          } else {
393            evokeByIFrame(schemeURL);
394            checkOpenFall = this.fallToFbUrl;
395          }
396  
397          if (typeof callback !== 'undefined') {
398            this.fallToCustomCb(callback);
399            return;
400          }
401  
402          if (!checkOpenFall) return;
403          checkOpenFall.call(this);
404        }
405      }]);
406  
407      return CallApp;
408    }();
409  
410    return CallApp;
411  
412  })));

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.