Created
June 5, 2015 07:39
-
-
Save minwe/9f7efada432e5965e0e9 to your computer and use it in GitHub Desktop.
main.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){ | |
'use strict'; | |
require('console-polyfill'); | |
var store = require('store'); | |
var Notify = require('notifyjs'); | |
var md5 = require('blueimp-md5'); | |
var detector = require('detector'); | |
var hbs = window.Handlebars; | |
var w = window; | |
var $ = window.jQuery || window.Zepto; | |
var browser = detector.browser; | |
var isIE = browser.ie; | |
var oldIE = isIE && browser.version < 10; | |
var $body = $('body'); | |
var $html = $('html'); | |
function onShowNotification() { | |
console.log('notification is shown!'); | |
} | |
function onCloseNotification() { | |
console.log('notification is closed!'); | |
} | |
function onClickNotification() { | |
console.log('notification was clicked!'); | |
} | |
function onErrorNotification() { | |
console.error('Error showing notification. ' + | |
'You may need to request permission.'); | |
} | |
function onPermissionGranted() { | |
console.log('Permission has been granted by the user'); | |
doNotification('你要捏代码已经复制到剪贴板,粘去吧 ^_^'); | |
} | |
function onPermissionDenied() { | |
console.warn('Permission has been denied by the user'); | |
} | |
function doNotification(msg) { | |
var myNotification = new Notify('嗨,骚年!', { | |
body: msg, | |
tag: 'amazeUI', | |
icon: '/i/app-icon72x72@2x.png', | |
notifyShow: onShowNotification, | |
notifyClose: onCloseNotification, | |
notifyClick: onClickNotification, | |
notifyError: onErrorNotification, | |
timeout: 3 | |
}); | |
myNotification.show(); | |
} | |
var initDuosuo = function() { | |
w.duoshuoQuery = { | |
short_name: 'amui' | |
}; | |
var $duoshuo = $('<script></script>', { | |
charset: 'utf-8', | |
src: (document.location.protocol === 'https:' ? | |
'https:' : 'http:') + '//static.duoshuo.com/embed.js' | |
}); | |
$body.append($duoshuo); | |
}; | |
$(window).on('load', function() { | |
$('.ds-thread').length && initDuosuo(); | |
}); | |
var amaze = {}; | |
amaze.auth = function() { | |
var $auth = $('.auth'); | |
var $user = $auth.find('#username'); | |
var $avatar = $auth.find('#user-avatar'); | |
$user.on('blur', function() { | |
var hash = md5($(this).val()); | |
$avatar.attr('src', | |
'http://www.gravatar.com/avatar/' + hash + '?d=mm&s=144'); | |
}); | |
}; | |
amaze.externalLink = function() { | |
var $doc = $('.doc-content'); | |
var $exLink = $doc.find('a[href^="http://"], a[href^="https://"]'). | |
not('.doc-example a'); | |
$exLink.addClass('external-link').attr('target', '_blank'); | |
}; | |
amaze.checkLogin = function() { | |
var storeEnabled = store && store.enabled; | |
var $header = $('#amz-header'); | |
var $profile = $header.find('.nav-profile.need-check'); | |
var $avatar = $profile.find('img'); | |
var loggedInStatusKey = '_amui_login_status'; | |
var now = new Date().getTime(); | |
if (storeEnabled) { | |
var localData = store.get(loggedInStatusKey); | |
if (localData) { | |
if (w.location.search.indexOf('logout') > -1) { | |
store.remove(loggedInStatusKey); | |
$profile.hide(); | |
return; | |
} | |
if ((now - localData.lastCheck) < 3600000) { | |
$avatar.attr('src', localData.avatar); | |
$profile.show().addClass('am-animation-fade'); | |
return; | |
} else { | |
store.remove(loggedInStatusKey); | |
} | |
} | |
} | |
$.getJSON('/api/user', function(data) { | |
if (data.loggedIn) { | |
$profile.show(); | |
$avatar.attr('src', data.avatar); | |
data.lastCheck = new Date().getTime(); | |
storeEnabled && store.set(loggedInStatusKey, data); | |
} else { | |
$profile.hide(); | |
} | |
}); | |
}; | |
amaze.zeroClip = function() { | |
if (!window.ZeroClipboard) { | |
return; | |
} | |
ZeroClipboard.config({ | |
moviePath: '/js/ZeroClipboard.swf', | |
hoverClass: 'doc-act-clip-hover' | |
}); | |
var copyBtn = '<div class="doc-actions"><div class="doc-act-inner">' + | |
'<span class="doc-act-clip am-icon-copy"> Copy</span></div></div>'; | |
var copyBtnNew = '<div class="doc-actions"><div class="doc-act-inner">' + | |
'<span class="doc-act-newwin am-icon-file-code-o"> New Win</span>' + | |
'<span class="doc-act-clip am-icon-copy"> Copy</span></div></div>'; | |
$('.doc-code').each(function() { | |
var $code = $(this); | |
var $prev = $code.prev(); | |
if ($prev.hasClass('doc-example')) { | |
if ($prev.attr('data-url')) { | |
$prev.before(copyBtnNew); | |
} else { | |
$prev.before(copyBtn); | |
} | |
} else { | |
$code.before(copyBtn); | |
} | |
}); | |
$('.doc-act-newwin').on('click', function(e) { | |
var $demo = $(this).parent().parent('.doc-actions').next('.doc-example'); | |
if ($demo.length && $demo.attr('data-url')) { | |
window.open($demo.attr('data-url') + '?_ver=' + | |
$(document.body).data('amui'), '', | |
'width=320px, height=480px, centerscreen=yes'); | |
} | |
}); | |
var codeClip = new ZeroClipboard($('.doc-act-clip')); | |
codeClip.on('ready', function(readyEvent) { | |
codeClip.on('copy', function(e) { | |
var $next = $(e.target).parent().parent().next(); | |
var $reqCode = $next.is('.doc-code') ? $next : $next.next('.doc-code'); | |
var data = $reqCode.text(); | |
if (data.indexOf('data-am-slider') > -1) { | |
data = data.replace(/"/g, '"'); | |
} | |
e.clipboardData.setData('text/plain', data); | |
}); | |
}); | |
// Copy finish | |
codeClip.on('aftercopy', function(e) { | |
if (Notify.needsPermission) { | |
Notify.requestPermission(onPermissionGranted, onPermissionDenied); | |
} else { | |
doNotification('你要捏代码已经复制到剪贴板,粘去吧 ^_^'); | |
} | |
if (console) { | |
console.log('Copied text to clipboard: ' + e.data['text/plain']); | |
} | |
}); | |
// Can't copy | |
codeClip.on('error', function(e) { | |
if (Notify.needsPermission) { | |
Notify.requestPermission(onPermissionGranted, onPermissionDenied); | |
} else { | |
doNotification('Something wrong :-(\n' + e.name); | |
} | |
}); | |
// Copy example | |
// Read: https://github.com/zeroclipboard/zeroclipboard/blob/1.x-master/docs/instructions.md | |
}; | |
amaze.toolbar = function() { | |
var $w = $(w); | |
var $toolbar = $('#amz-toolbar'); | |
var $goTop = $toolbar.find('#amz-go-top'); | |
if (!$goTop.length) { | |
return; | |
} | |
$goTop.on('click', function(e) { | |
e.preventDefault(); | |
if (oldIE) { | |
$('html, body').animate({scrollTop: 0}, 500); | |
return false; | |
} | |
$(w).smoothScroll(0); | |
}); | |
function checkScrollTop() { | |
if ($w.scrollTop() > 10) { | |
$goTop.addClass('am-active'); | |
} else { | |
$goTop.removeClass('am-active'); | |
} | |
} | |
function checkWinWidth() { | |
if ($w.width() > 1110) { | |
$toolbar.css({right: ($w.width() - 1110) / 2}); | |
} else { | |
$toolbar.css({right: '10px'}); | |
} | |
} | |
checkScrollTop(); | |
checkWinWidth(); | |
$w.on('scroll', $.AMUI.utils.debounce(checkScrollTop, 100)); | |
$w.on('resize', $.AMUI.utils.debounce(checkWinWidth, 100)); | |
}; | |
amaze.standaloneMode = function() { | |
if (window.navigator.standalone) { // WebApp Mode | |
$(document).on('click', 'a', function(e) { | |
var link = $(this).attr('href'); | |
if (link && (link.indexOf('http') || ~link.indexOf(location.host))) { | |
e.preventDefault(); | |
location.href = link; | |
} | |
}); | |
} | |
}; | |
amaze.pageChange = function() { | |
var animationSupported = $.AMUI.support.animation; | |
var $bd = $('body'); | |
if (animationSupported) { | |
$(document).on('click', 'a', function(e) { | |
var link = $(this).attr('href'); | |
if (link && (link.indexOf('http') || ~link.indexOf(location.host))) { | |
e.preventDefault(); | |
$bd.addClass('doc-slide-out'); | |
$bd.one(animationSupported.end, function() { | |
location.href = link; | |
}); | |
} | |
}); | |
$bd.addClass('doc-slide-in'); | |
$bd.one(animationSupported.end, function() { | |
$bd.removeClass('doc-slide-in'); | |
}); | |
} | |
}; | |
amaze.getIssues = function() { | |
var issues = 'https://api.github.com/repos/allmobilize/amazeui/issues?state=all&labels='; | |
var labels = []; | |
var $main = $('#amz-main'); | |
var component = $main.data('tag'); | |
var $tpl = $main.find('#issue-list-tpl'); | |
var $issueList = $main.find('#issue-list'); | |
var source = $tpl.text() || ''; | |
var template = hbs && hbs.compile(source); | |
labels.push('v' + $(document.body).data('amui')); | |
labels.push(component); | |
if (component && template) { | |
$.getJSON(issues + labels.join(','), function(data) { | |
data && data.length && $issueList.html(template(data)); | |
}); | |
} | |
}; | |
amaze.sticky = function() { | |
var userAgent = navigator.userAgent.toLowerCase(); | |
// Test if the browser is IE and check the version number is lower than 9 | |
if (/msie/.test(userAgent) && parseFloat((userAgent. | |
match(/.*(?:rv|ie)[\/: ](.+?)([ \);]|$)/) || [])[1]) < 10) { | |
return; | |
} | |
var $bar = $('#amz-offcanvas'); | |
var $pager = $bar.find('.amz-pager'); | |
var $pagerLink = $pager.find('a'); | |
var $sidebar = $bar.find('.amz-sidebar'); | |
$bar.sticky({ | |
top: 10, | |
bottom: function() { | |
return $('.amz-footer').height() + 25; | |
}, | |
media: 641 | |
}); | |
function barMaxHeight() { | |
var $footer = $('.amz-footer'); | |
// jQuery height() 返回的值不包含 padding 和 border | |
var footerHeight = $footer[$.fn.outerHeight ? 'outerHeight' : 'height'](); | |
var h = $(w).height() - 20 - footerHeight; | |
if ($bar.hasClass('am-sticky')) { | |
$sidebar.css({'max-height': h}); | |
$bar.css({'max-height': h}); | |
} else { | |
$sidebar.css({'max-height': ''}); | |
$bar.css({'max-height': ''}); | |
} | |
if (h > $sidebar.height()) { | |
$pager.removeClass('am-active'); | |
} else { | |
$pager.addClass('am-active'); | |
} | |
$pager.css({top: $sidebar.height() / 2}); | |
} | |
barMaxHeight(); | |
setTimeout(barMaxHeight, 119); | |
$(w).on('scroll resize', $.AMUI.utils.debounce(barMaxHeight, 10)); | |
$pager.on('click', 'a', function(e) { | |
e.preventDefault(); | |
if ($(this).hasClass('am-disabled')) { | |
return; | |
} | |
var data = $(this).data('rel'); | |
var scrollTop = $sidebar.scrollTop(); | |
var delta = 200; | |
if (data === 'scrollUp') { | |
$sidebar.smoothScroll({position: scrollTop - delta}); | |
} else { | |
$sidebar.smoothScroll({position: scrollTop + delta}); | |
} | |
}); | |
function checkScroll() { | |
var disabled = 'am-disabled'; | |
if ($sidebar.scrollTop() === 0) { | |
$pagerLink.eq(0).addClass(disabled); | |
} else { | |
$pagerLink.eq(0).removeClass(disabled); | |
} | |
// TODO: 滚动到底部判断 | |
} | |
$sidebar.on('scroll', $.AMUI.utils.debounce(checkScroll, 50)); | |
// http://stackoverflow.com/questions/7154967/jquery-detect-scrolldown | |
// IE, Opera, Safari | |
$sidebar.on('mousewheel', function(e) { | |
e.preventDefault(); | |
// jquery store originalEvent | |
var event = e.originalEvent || e; | |
var direction = event.wheelDelta < 0 ? 'down' : 'up'; | |
mouseScroll(direction); | |
}).on('DOMMouseScroll', function(e) { // Firefox | |
e.preventDefault(); | |
var event = e.originalEvent || e; | |
mouseScroll(event.detail > 0 ? 'down' : 'up'); | |
}); | |
function mouseScroll(direction, delta) { | |
direction = direction || 'up'; | |
delta = delta || 100; | |
var scrollTo = (direction === 'up' ? | |
-delta : delta) + $sidebar.scrollTop(); | |
$sidebar.scrollTop(scrollTo); | |
} | |
}; | |
amaze.docToc = function() { | |
var $toc = $('.doc-toc-bd > .md-toc'); | |
var $tocParent = $toc.find('>li').has('>ul'); | |
$tocParent.addClass('am-parent'); | |
$tocParent.on('mouseenter', function() { | |
var $subToc = $(this).children('ul'); | |
$subToc.collapse('open'); | |
$(this).addClass('am-open'); | |
// $(this).siblings('li').children('ul.am-in').collapse('close'); | |
}); | |
$toc.find('a').on('click', function(e) { | |
e.preventDefault(); | |
var anchor = decodeURIComponent($(this).attr('href')); | |
var $anchor = $(anchor); | |
$anchor.length && $(w).smoothScroll({position: $anchor.offset().top}); | |
}); | |
// TODO: 使用 pushState | |
}; | |
amaze.cse = function() { | |
var $cse = $('#amz-header').find('.amz-cse'); | |
var $q = $cse.find('[name="q"]'); | |
var timer; | |
$q.on('focus', function() { | |
$cse.addClass('am-active'); | |
clearTimeout(timer); | |
}).on('blur', function() { | |
timer = setTimeout(function() { | |
$cse.removeClass('am-active'); | |
}, 1000); | |
}); | |
}; | |
amaze.init = function() { | |
this.auth(); | |
this.externalLink(); | |
this.checkLogin(); | |
this.zeroClip(); | |
this.toolbar(); | |
this.standaloneMode(); | |
this.getIssues(); | |
this.docToc(); | |
this.sticky(); | |
this.cse(); | |
// this.pageChange(); | |
}; | |
$(function() { | |
var $docContent = $('#amz-main').find('.doc-content'); | |
var $toc = $docContent.find('.doc-toc'); | |
if ($toc.next().is('h1')) { | |
$docContent.find('hr').first().after($toc); | |
} | |
if (isIE && browser.version < 9) { | |
return false; | |
} | |
amaze.init(); | |
$('.amz-social [data-am-modal]').on('click', function(e) { | |
e.preventDefault(); | |
}); | |
var iOS = /(iPad|iPhone|iPod)/g.test(navigator.userAgent); | |
if (iOS) { | |
$html.addClass('ios'); | |
} | |
$('.new-issue').each(function() { | |
this.href += encodeURIComponent('```\n' + navigator.userAgent + '\n```\n'); | |
}); | |
}); | |
},{"blueimp-md5":2,"console-polyfill":3,"detector":4,"notifyjs":6,"store":7}],2:[function(require,module,exports){ | |
/* | |
* JavaScript MD5 1.0.1 | |
* https://github.com/blueimp/JavaScript-MD5 | |
* | |
* Copyright 2011, Sebastian Tschan | |
* https://blueimp.net | |
* | |
* Licensed under the MIT license: | |
* http://www.opensource.org/licenses/MIT | |
* | |
* Based on | |
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message | |
* Digest Algorithm, as defined in RFC 1321. | |
* Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 | |
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet | |
* Distributed under the BSD License | |
* See http://pajhome.org.uk/crypt/md5 for more info. | |
*/ | |
/*jslint bitwise: true */ | |
/*global unescape, define */ | |
(function ($) { | |
'use strict'; | |
/* | |
* Add integers, wrapping at 2^32. This uses 16-bit operations internally | |
* to work around bugs in some JS interpreters. | |
*/ | |
function safe_add(x, y) { | |
var lsw = (x & 0xFFFF) + (y & 0xFFFF), | |
msw = (x >> 16) + (y >> 16) + (lsw >> 16); | |
return (msw << 16) | (lsw & 0xFFFF); | |
} | |
/* | |
* Bitwise rotate a 32-bit number to the left. | |
*/ | |
function bit_rol(num, cnt) { | |
return (num << cnt) | (num >>> (32 - cnt)); | |
} | |
/* | |
* These functions implement the four basic operations the algorithm uses. | |
*/ | |
function md5_cmn(q, a, b, x, s, t) { | |
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b); | |
} | |
function md5_ff(a, b, c, d, x, s, t) { | |
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); | |
} | |
function md5_gg(a, b, c, d, x, s, t) { | |
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); | |
} | |
function md5_hh(a, b, c, d, x, s, t) { | |
return md5_cmn(b ^ c ^ d, a, b, x, s, t); | |
} | |
function md5_ii(a, b, c, d, x, s, t) { | |
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); | |
} | |
/* | |
* Calculate the MD5 of an array of little-endian words, and a bit length. | |
*/ | |
function binl_md5(x, len) { | |
/* append padding */ | |
x[len >> 5] |= 0x80 << (len % 32); | |
x[(((len + 64) >>> 9) << 4) + 14] = len; | |
var i, olda, oldb, oldc, oldd, | |
a = 1732584193, | |
b = -271733879, | |
c = -1732584194, | |
d = 271733878; | |
for (i = 0; i < x.length; i += 16) { | |
olda = a; | |
oldb = b; | |
oldc = c; | |
oldd = d; | |
a = md5_ff(a, b, c, d, x[i], 7, -680876936); | |
d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586); | |
c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819); | |
b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330); | |
a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897); | |
d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426); | |
c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341); | |
b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983); | |
a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416); | |
d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417); | |
c = md5_ff(c, d, a, b, x[i + 10], 17, -42063); | |
b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162); | |
a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682); | |
d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101); | |
c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290); | |
b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329); | |
a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510); | |
d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632); | |
c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713); | |
b = md5_gg(b, c, d, a, x[i], 20, -373897302); | |
a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691); | |
d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083); | |
c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335); | |
b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848); | |
a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438); | |
d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690); | |
c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961); | |
b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501); | |
a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467); | |
d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784); | |
c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473); | |
b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734); | |
a = md5_hh(a, b, c, d, x[i + 5], 4, -378558); | |
d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463); | |
c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562); | |
b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556); | |
a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060); | |
d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353); | |
c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632); | |
b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640); | |
a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174); | |
d = md5_hh(d, a, b, c, x[i], 11, -358537222); | |
c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979); | |
b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189); | |
a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487); | |
d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835); | |
c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520); | |
b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651); | |
a = md5_ii(a, b, c, d, x[i], 6, -198630844); | |
d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415); | |
c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905); | |
b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055); | |
a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571); | |
d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606); | |
c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523); | |
b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799); | |
a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359); | |
d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744); | |
c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380); | |
b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649); | |
a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070); | |
d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379); | |
c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259); | |
b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551); | |
a = safe_add(a, olda); | |
b = safe_add(b, oldb); | |
c = safe_add(c, oldc); | |
d = safe_add(d, oldd); | |
} | |
return [a, b, c, d]; | |
} | |
/* | |
* Convert an array of little-endian words to a string | |
*/ | |
function binl2rstr(input) { | |
var i, | |
output = ''; | |
for (i = 0; i < input.length * 32; i += 8) { | |
output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF); | |
} | |
return output; | |
} | |
/* | |
* Convert a raw string to an array of little-endian words | |
* Characters >255 have their high-byte silently ignored. | |
*/ | |
function rstr2binl(input) { | |
var i, | |
output = []; | |
output[(input.length >> 2) - 1] = undefined; | |
for (i = 0; i < output.length; i += 1) { | |
output[i] = 0; | |
} | |
for (i = 0; i < input.length * 8; i += 8) { | |
output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32); | |
} | |
return output; | |
} | |
/* | |
* Calculate the MD5 of a raw string | |
*/ | |
function rstr_md5(s) { | |
return binl2rstr(binl_md5(rstr2binl(s), s.length * 8)); | |
} | |
/* | |
* Calculate the HMAC-MD5, of a key and some data (raw strings) | |
*/ | |
function rstr_hmac_md5(key, data) { | |
var i, | |
bkey = rstr2binl(key), | |
ipad = [], | |
opad = [], | |
hash; | |
ipad[15] = opad[15] = undefined; | |
if (bkey.length > 16) { | |
bkey = binl_md5(bkey, key.length * 8); | |
} | |
for (i = 0; i < 16; i += 1) { | |
ipad[i] = bkey[i] ^ 0x36363636; | |
opad[i] = bkey[i] ^ 0x5C5C5C5C; | |
} | |
hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); | |
return binl2rstr(binl_md5(opad.concat(hash), 512 + 128)); | |
} | |
/* | |
* Convert a raw string to a hex string | |
*/ | |
function rstr2hex(input) { | |
var hex_tab = '0123456789abcdef', | |
output = '', | |
x, | |
i; | |
for (i = 0; i < input.length; i += 1) { | |
x = input.charCodeAt(i); | |
output += hex_tab.charAt((x >>> 4) & 0x0F) + | |
hex_tab.charAt(x & 0x0F); | |
} | |
return output; | |
} | |
/* | |
* Encode a string as utf-8 | |
*/ | |
function str2rstr_utf8(input) { | |
return unescape(encodeURIComponent(input)); | |
} | |
/* | |
* Take string arguments and return either raw or hex encoded strings | |
*/ | |
function raw_md5(s) { | |
return rstr_md5(str2rstr_utf8(s)); | |
} | |
function hex_md5(s) { | |
return rstr2hex(raw_md5(s)); | |
} | |
function raw_hmac_md5(k, d) { | |
return rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)); | |
} | |
function hex_hmac_md5(k, d) { | |
return rstr2hex(raw_hmac_md5(k, d)); | |
} | |
function md5(string, key, raw) { | |
if (!key) { | |
if (!raw) { | |
return hex_md5(string); | |
} | |
return raw_md5(string); | |
} | |
if (!raw) { | |
return hex_hmac_md5(key, string); | |
} | |
return raw_hmac_md5(key, string); | |
} | |
if (typeof define === 'function' && define.amd) { | |
define(function () { | |
return md5; | |
}); | |
} else { | |
$.md5 = md5; | |
} | |
}(this)); | |
},{}],3:[function(require,module,exports){ | |
// Console-polyfill. MIT license. | |
// https://github.com/paulmillr/console-polyfill | |
// Make it safe to do console.log() always. | |
(function(con) { | |
'use strict'; | |
var prop, method; | |
var empty = {}; | |
var dummy = function() {}; | |
var properties = 'memory'.split(','); | |
var methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' + | |
'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' + | |
'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn').split(','); | |
while (prop = properties.pop()) con[prop] = con[prop] || empty; | |
while (method = methods.pop()) con[method] = con[method] || dummy; | |
})(this.console = this.console || {}); // Using `this` for web workers. | |
},{}],4:[function(require,module,exports){ | |
(function (process){ | |
var detector = {}; | |
var NA_VERSION = "-1"; | |
var win = this; | |
var external; | |
var re_msie = /\b(?:msie |ie |trident\/[0-9].*rv[ :])([0-9.]+)/; | |
var re_blackberry_10 = /\bbb10\b.+?\bversion\/([\d.]+)/; | |
var re_blackberry_6_7 = /\bblackberry\b.+\bversion\/([\d.]+)/; | |
var re_blackberry_4_5 = /\bblackberry\d+\/([\d.]+)/; | |
function toString(object){ | |
return Object.prototype.toString.call(object); | |
} | |
function isObject(object){ | |
return toString(object) === "[object Object]"; | |
} | |
function isFunction(object){ | |
return toString(object) === "[object Function]"; | |
} | |
function each(object, factory, argument){ | |
for(var i=0,b,l=object.length; i<l; i++){ | |
if(factory.call(object, object[i], i) === false){break;} | |
} | |
} | |
// 硬件设备信息识别表达式。 | |
// 使用数组可以按优先级排序。 | |
var DEVICES = [ | |
["nokia", function(ua){ | |
// 不能将两个表达式合并,因为可能出现 "nokia; nokia 960" | |
// 这种情况下会优先识别出 nokia/-1 | |
if(ua.indexOf("nokia ") !== -1){ | |
return /\bnokia ([0-9]+)?/; | |
}else{ | |
return /\bnokia([a-z0-9]+)?/; | |
} | |
}], | |
// 三星有 Android 和 WP 设备。 | |
["samsung", function(ua){ | |
if(ua.indexOf("samsung") !== -1){ | |
return /\bsamsung(?:[ \-](?:sgh|gt|sm))?-([a-z0-9]+)/; | |
}else{ | |
return /\b(?:sgh|sch|gt|sm)-([a-z0-9]+)/; | |
} | |
}], | |
["wp", function(ua){ | |
return ua.indexOf("windows phone ") !== -1 || | |
ua.indexOf("xblwp") !== -1 || | |
ua.indexOf("zunewp") !== -1 || | |
ua.indexOf("windows ce") !== -1; | |
}], | |
["pc", "windows"], | |
["ipad", "ipad"], | |
// ipod 规则应置于 iphone 之前。 | |
["ipod", "ipod"], | |
["iphone", /\biphone\b|\biph(\d)/], | |
["mac", "macintosh"], | |
// 小米 | |
["mi", /\bmi[ \-]?([a-z0-9 ]+(?= build|\)))/], | |
// 红米 | |
['hongmi', /\bhm[ \-]?([a-z0-9]+)/], | |
["aliyun", /\baliyunos\b(?:[\-](\d+))?/], | |
["meizu", function(ua) { | |
return ua.indexOf("meizu") >= 0 ? | |
/\bmeizu[\/ ]([a-z0-9]+)\b/ | |
: | |
/\bm([0-9x]{1,3})\b/ | |
}], | |
["nexus", /\bnexus ([0-9s.]+)/], | |
["huawei", function(ua){ | |
var re_mediapad = /\bmediapad (.+?)(?= build\/huaweimediapad\b)/; | |
if(ua.indexOf("huawei-huawei") !== -1){ | |
return /\bhuawei\-huawei\-([a-z0-9\-]+)/; | |
}else if(re_mediapad.test(ua)){ | |
return re_mediapad; | |
}else{ | |
return /\bhuawei[ _\-]?([a-z0-9]+)/; | |
} | |
}], | |
["lenovo", function(ua){ | |
if(ua.indexOf("lenovo-lenovo") !== -1){ | |
return /\blenovo\-lenovo[ \-]([a-z0-9]+)/; | |
}else{ | |
return /\blenovo[ \-]?([a-z0-9]+)/; | |
} | |
}], | |
// 中兴 | |
["zte", function(ua){ | |
if(/\bzte\-[tu]/.test(ua)){ | |
return /\bzte-[tu][ _\-]?([a-su-z0-9\+]+)/; | |
}else{ | |
return /\bzte[ _\-]?([a-su-z0-9\+]+)/; | |
} | |
}], | |
// 步步高 | |
["vivo", /\bvivo(?: ([a-z0-9]+))?/], | |
["htc", function(ua){ | |
if(/\bhtc[a-z0-9 _\-]+(?= build\b)/.test(ua)){ | |
return /\bhtc[ _\-]?([a-z0-9 ]+(?= build))/; | |
}else{ | |
return /\bhtc[ _\-]?([a-z0-9 ]+)/; | |
} | |
}], | |
["oppo", /\boppo[_]([a-z0-9]+)/], | |
["konka", /\bkonka[_\-]([a-z0-9]+)/], | |
["sonyericsson", /\bmt([a-z0-9]+)/], | |
["coolpad", /\bcoolpad[_ ]?([a-z0-9]+)/], | |
["lg", /\blg[\-]([a-z0-9]+)/], | |
["android", /\bandroid\b|\badr\b/], | |
["blackberry", function(ua){ | |
if (ua.indexOf("blackberry") >= 0) { | |
return /\bblackberry\s?(\d+)/; | |
} | |
return "bb10"; | |
}] | |
]; | |
// 操作系统信息识别表达式 | |
var OS = [ | |
["wp", function(ua){ | |
if(ua.indexOf("windows phone ") !== -1){ | |
return /\bwindows phone (?:os )?([0-9.]+)/; | |
}else if(ua.indexOf("xblwp") !== -1){ | |
return /\bxblwp([0-9.]+)/; | |
}else if(ua.indexOf("zunewp") !== -1){ | |
return /\bzunewp([0-9.]+)/; | |
} | |
return "windows phone"; | |
}], | |
["windows", /\bwindows nt ([0-9.]+)/], | |
["macosx", /\bmac os x ([0-9._]+)/], | |
["ios", function(ua){ | |
if(/\bcpu(?: iphone)? os /.test(ua)){ | |
return /\bcpu(?: iphone)? os ([0-9._]+)/; | |
}else if(ua.indexOf("iph os ") !== -1){ | |
return /\biph os ([0-9_]+)/; | |
}else{ | |
return /\bios\b/; | |
} | |
}], | |
["yunos", /\baliyunos ([0-9.]+)/], | |
["android", function(ua){ | |
if(ua.indexOf("android") >= 0){ | |
return /\bandroid[ \/-]?([0-9.x]+)?/; | |
}else if(ua.indexOf("adr") >= 0){ | |
if(ua.indexOf("mqqbrowser") >= 0){ | |
return /\badr[ ]\(linux; u; ([0-9.]+)?/; | |
}else{ | |
return /\badr(?:[ ]([0-9.]+))?/; | |
} | |
} | |
return "android"; | |
//return /\b(?:android|\badr)(?:[\/\- ](?:\(linux; u; )?)?([0-9.x]+)?/; | |
}], | |
["chromeos", /\bcros i686 ([0-9.]+)/], | |
["linux", "linux"], | |
["windowsce", /\bwindows ce(?: ([0-9.]+))?/], | |
["symbian", /\bsymbian(?:os)?\/([0-9.]+)/], | |
["blackberry", function(ua){ | |
var m = ua.match(re_blackberry_10) || | |
ua.match(re_blackberry_6_7) || | |
ua.match(re_blackberry_4_5); | |
return m ? {version: m[1]} : "blackberry"; | |
}] | |
]; | |
// 解析使用 Trident 内核的浏览器的 `浏览器模式` 和 `文档模式` 信息。 | |
// @param {String} ua, userAgent string. | |
// @return {Object} | |
function IEMode(ua){ | |
if(!re_msie.test(ua)){return null;} | |
var m, | |
engineMode, engineVersion, | |
browserMode, browserVersion, | |
compatible=false; | |
// IE8 及其以上提供有 Trident 信息, | |
// 默认的兼容模式,UA 中 Trident 版本不发生变化。 | |
if(ua.indexOf("trident/") !== -1){ | |
m = /\btrident\/([0-9.]+)/.exec(ua); | |
if(m && m.length>=2){ | |
// 真实引擎版本。 | |
engineVersion = m[1]; | |
var v_version = m[1].split("."); | |
v_version[0] = parseInt(v_version[0], 10) + 4; | |
browserVersion = v_version.join("."); | |
} | |
} | |
m = re_msie.exec(ua); | |
browserMode = m[1]; | |
var v_mode = m[1].split("."); | |
if("undefined" === typeof browserVersion){ | |
browserVersion = browserMode; | |
} | |
v_mode[0] = parseInt(v_mode[0], 10) - 4; | |
engineMode = v_mode.join("."); | |
if("undefined" === typeof engineVersion){ | |
engineVersion = engineMode; | |
} | |
return { | |
browserVersion: browserVersion, | |
browserMode: browserMode, | |
engineVersion: engineVersion, | |
engineMode: engineMode, | |
compatible: engineVersion !== engineMode | |
}; | |
} | |
// 针对同源的 TheWorld 和 360 的 external 对象进行检测。 | |
// @param {String} key, 关键字,用于检测浏览器的安装路径中出现的关键字。 | |
// @return {Undefined,Boolean,Object} 返回 undefined 或 false 表示检测未命中。 | |
function checkTW360External(key){ | |
if(!external){return;} // return undefined. | |
try{ | |
// 360安装路径: | |
// C:%5CPROGRA~1%5C360%5C360se3%5C360SE.exe | |
var runpath = external.twGetRunPath.toLowerCase(); | |
// 360SE 3.x ~ 5.x support. | |
// 暴露的 external.twGetVersion 和 external.twGetSecurityID 均为 undefined。 | |
// 因此只能用 try/catch 而无法使用特性判断。 | |
var security = external.twGetSecurityID(win); | |
var version = external.twGetVersion(security); | |
if(runpath && runpath.indexOf(key) === -1){return false;} | |
if(version){return {version: version};} | |
}catch(ex){} | |
} | |
var ENGINE = [ | |
["trident", re_msie], | |
["blink", function(ua){ | |
return "chrome" in win && "CSS" in win && /\bapplewebkit[\/]?([0-9.+]+)/; | |
}], | |
["webkit", /\bapplewebkit[\/]?([0-9.+]+)/], | |
["gecko", function(ua){ | |
var match; | |
if (match = ua.match(/\brv:([\d\w.]+).*\bgecko\/(\d+)/)) { | |
return { | |
version: match[1] + "." + match[2] | |
} | |
} | |
}], | |
["presto", /\bpresto\/([0-9.]+)/], | |
["androidwebkit", /\bandroidwebkit\/([0-9.]+)/], | |
["coolpadwebkit", /\bcoolpadwebkit\/([0-9.]+)/], | |
["u2", /\bu2\/([0-9.]+)/], | |
["u3", /\bu3\/([0-9.]+)/] | |
]; | |
var BROWSER = [ | |
// Sogou. | |
["sogou", function(ua){ | |
if (ua.indexOf("sogoumobilebrowser") >= 0) { | |
return /sogoumobilebrowser\/([0-9.]+)/ | |
} else if (ua.indexOf("sogoumse") >= 0){ | |
return true; | |
} | |
return / se ([0-9.x]+)/; | |
}], | |
// TheWorld (世界之窗) | |
// 由于裙带关系,TheWorld API 与 360 高度重合。 | |
// 只能通过 UA 和程序安装路径中的应用程序名来区分。 | |
// TheWorld 的 UA 比 360 更靠谱,所有将 TheWorld 的规则放置到 360 之前。 | |
["theworld", function(ua){ | |
var x = checkTW360External("theworld"); | |
if(typeof x !== "undefined"){return x;} | |
return "theworld"; | |
}], | |
// 360SE, 360EE. | |
["360", function(ua) { | |
var x = checkTW360External("360se"); | |
if(typeof x !== "undefined"){return x;} | |
if(ua.indexOf("360 aphone browser") !== -1){ | |
return /\b360 aphone browser \(([^\)]+)\)/; | |
} | |
return /\b360(?:se|ee|chrome|browser)\b/; | |
}], | |
// Maxthon | |
["maxthon", function(ua){ | |
try{ | |
if(external && (external.mxVersion || external.max_version)){ | |
return { | |
version: external.mxVersion || external.max_version | |
}; | |
} | |
}catch(ex){} | |
return /\b(?:maxthon|mxbrowser)(?:[ \/]([0-9.]+))?/; | |
}], | |
["qq", /\bm?qqbrowser\/([0-9.]+)/], | |
["green", "greenbrowser"], | |
["tt", /\btencenttraveler ([0-9.]+)/], | |
["liebao", function(ua){ | |
if (ua.indexOf("liebaofast") >= 0){ | |
return /\bliebaofast\/([0-9.]+)/; | |
} | |
if(ua.indexOf("lbbrowser") === -1){return false;} | |
var version; | |
try{ | |
if(external && external.LiebaoGetVersion){ | |
version = external.LiebaoGetVersion(); | |
} | |
}catch(ex){} | |
return { | |
version: version || NA_VERSION | |
}; | |
}], | |
["tao", /\btaobrowser\/([0-9.]+)/], | |
["coolnovo", /\bcoolnovo\/([0-9.]+)/], | |
["saayaa", "saayaa"], | |
// 有基于 Chromniun 的急速模式和基于 IE 的兼容模式。必须在 IE 的规则之前。 | |
["baidu", /\b(?:ba?idubrowser|baiduhd)[ \/]([0-9.x]+)/], | |
// 后面会做修复版本号,这里只要能识别是 IE 即可。 | |
["ie", re_msie], | |
["mi", /\bmiuibrowser\/([0-9.]+)/], | |
// Opera 15 之后开始使用 Chromniun 内核,需要放在 Chrome 的规则之前。 | |
["opera", function(ua){ | |
var re_opera_old = /\bopera.+version\/([0-9.ab]+)/; | |
var re_opera_new = /\bopr\/([0-9.]+)/; | |
return re_opera_old.test(ua) ? re_opera_old : re_opera_new; | |
}], | |
["oupeng", /\boupeng\/([0-9.]+)/], | |
["yandex", /yabrowser\/([0-9.]+)/], | |
// 支付宝手机客户端 | |
["ali-ap", function(ua){ | |
if(ua.indexOf("aliapp") > 0){ | |
return /\baliapp\(ap\/([0-9.]+)\)/; | |
}else{ | |
return /\balipayclient\/([0-9.]+)\b/; | |
} | |
}], | |
// 支付宝平板客户端 | |
["ali-ap-pd", /\baliapp\(ap-pd\/([0-9.]+)\)/], | |
// 支付宝商户客户端 | |
["ali-am", /\baliapp\(am\/([0-9.]+)\)/], | |
// 淘宝手机客户端 | |
["ali-tb", /\baliapp\(tb\/([0-9.]+)\)/], | |
// 淘宝平板客户端 | |
["ali-tb-pd", /\baliapp\(tb-pd\/([0-9.]+)\)/], | |
// 天猫手机客户端 | |
["ali-tm", /\baliapp\(tm\/([0-9.]+)\)/], | |
// 天猫平板客户端 | |
["ali-tm-pd", /\baliapp\(tm-pd\/([0-9.]+)\)/], | |
// UC 浏览器,可能会被识别为 Android 浏览器,规则需要前置。 | |
// UC 桌面版浏览器携带 Chrome 信息,需要放在 Chrome 之前。 | |
["uc", function(ua){ | |
if(ua.indexOf("ucbrowser/") >= 0){ | |
return /\bucbrowser\/([0-9.]+)/; | |
} else if(ua.indexOf("ubrowser/") >= 0){ | |
return /\bubrowser\/([0-9.]+)/; | |
}else if(/\buc\/[0-9]/.test(ua)){ | |
return /\buc\/([0-9.]+)/; | |
}else if(ua.indexOf("ucweb") >= 0){ | |
// `ucweb/2.0` is compony info. | |
// `UCWEB8.7.2.214/145/800` is browser info. | |
return /\bucweb([0-9.]+)?/; | |
}else{ | |
return /\b(?:ucbrowser|uc)\b/; | |
} | |
}], | |
["chrome", / (?:chrome|crios|crmo)\/([0-9.]+)/], | |
// Android 默认浏览器。该规则需要在 safari 之前。 | |
["android", function(ua){ | |
if(ua.indexOf("android") === -1){return;} | |
return /\bversion\/([0-9.]+(?: beta)?)/; | |
}], | |
["blackberry", function(ua){ | |
var m = ua.match(re_blackberry_10) || | |
ua.match(re_blackberry_6_7) || | |
ua.match(re_blackberry_4_5); | |
return m ? {version: m[1]} : "blackberry"; | |
}], | |
["safari", /\bversion\/([0-9.]+(?: beta)?)(?: mobile(?:\/[a-z0-9]+)?)? safari\//], | |
// 如果不能被识别为 Safari,则猜测是 WebView。 | |
["webview", /\bcpu(?: iphone)? os (?:[0-9._]+).+\bapplewebkit\b/], | |
["firefox", /\bfirefox\/([0-9.ab]+)/], | |
["nokia", /\bnokiabrowser\/([0-9.]+)/] | |
]; | |
// UserAgent Detector. | |
// @param {String} ua, userAgent. | |
// @param {Object} expression | |
// @return {Object} | |
// 返回 null 表示当前表达式未匹配成功。 | |
function detect(name, expression, ua){ | |
var expr = isFunction(expression) ? expression.call(null, ua) : expression; | |
if(!expr){return null;} | |
var info = { | |
name: name, | |
version: NA_VERSION, | |
codename: "" | |
}; | |
var t = toString(expr); | |
if(expr === true){ | |
return info; | |
}else if(t === "[object String]"){ | |
if(ua.indexOf(expr) !== -1){ | |
return info; | |
} | |
}else if(isObject(expr)){ // Object | |
if(expr.hasOwnProperty("version")){ | |
info.version = expr.version; | |
} | |
return info; | |
}else if(expr.exec){ // RegExp | |
var m = expr.exec(ua); | |
if(m){ | |
if(m.length >= 2 && m[1]){ | |
info.version = m[1].replace(/_/g, "."); | |
}else{ | |
info.version = NA_VERSION; | |
} | |
return info; | |
} | |
} | |
} | |
var na = {name:"na", version:NA_VERSION}; | |
// 初始化识别。 | |
function init(ua, patterns, factory, detector){ | |
var detected = na; | |
each(patterns, function(pattern){ | |
var d = detect(pattern[0], pattern[1], ua); | |
if(d){ | |
detected = d; | |
return false; | |
} | |
}); | |
factory.call(detector, detected.name, detected.version); | |
} | |
// 解析 UserAgent 字符串 | |
// @param {String} ua, userAgent string. | |
// @return {Object} | |
var parse = function(ua){ | |
ua = (ua || "").toLowerCase(); | |
var d = {}; | |
init(ua, DEVICES, function(name, version){ | |
var v = parseFloat(version); | |
d.device = { | |
name: name, | |
version: v, | |
fullVersion: version | |
}; | |
d.device[name] = v; | |
}, d); | |
init(ua, OS, function(name, version){ | |
var v = parseFloat(version); | |
d.os = { | |
name: name, | |
version: v, | |
fullVersion: version | |
}; | |
d.os[name] = v; | |
}, d); | |
var ieCore = IEMode(ua); | |
init(ua, ENGINE, function(name, version){ | |
var mode = version; | |
// IE 内核的浏览器,修复版本号及兼容模式。 | |
if(ieCore){ | |
version = ieCore.engineVersion || ieCore.engineMode; | |
mode = ieCore.engineMode; | |
} | |
var v = parseFloat(version); | |
d.engine = { | |
name: name, | |
version: v, | |
fullVersion: version, | |
mode: parseFloat(mode), | |
fullMode: mode, | |
compatible: ieCore ? ieCore.compatible : false | |
}; | |
d.engine[name] = v; | |
}, d); | |
init(ua, BROWSER, function(name, version){ | |
var mode = version; | |
// IE 内核的浏览器,修复浏览器版本及兼容模式。 | |
if(ieCore){ | |
// 仅修改 IE 浏览器的版本,其他 IE 内核的版本不修改。 | |
if(name === "ie"){ | |
version = ieCore.browserVersion; | |
} | |
mode = ieCore.browserMode; | |
} | |
var v = parseFloat(version); | |
d.browser = { | |
name: name, | |
version: v, | |
fullVersion: version, | |
mode: parseFloat(mode), | |
fullMode: mode, | |
compatible: ieCore ? ieCore.compatible : false | |
}; | |
d.browser[name] = v; | |
}, d); | |
return d; | |
}; | |
// NodeJS. | |
if(typeof process === "object" && process.toString() === "[object process]"){ | |
// 加载更多的规则。 | |
var morerule = module["require"]("./morerule"); | |
[].unshift.apply(DEVICES, morerule.DEVICES || []); | |
[].unshift.apply(OS, morerule.OS || []); | |
[].unshift.apply(BROWSER, morerule.BROWSER || []); | |
[].unshift.apply(ENGINE, morerule.ENGINE || []); | |
}else{ | |
var userAgent = navigator.userAgent || ""; | |
//var platform = navigator.platform || ""; | |
var appVersion = navigator.appVersion || ""; | |
var vendor = navigator.vendor || ""; | |
external = win.external; | |
detector = parse(userAgent + " " + appVersion + " " + vendor); | |
} | |
// exports `parse()` API anyway. | |
detector.parse = parse; | |
module.exports = detector; | |
}).call(this,require("oMfpAn")) | |
},{"oMfpAn":5}],5:[function(require,module,exports){ | |
// shim for using process in browser | |
var process = module.exports = {}; | |
process.nextTick = (function () { | |
var canSetImmediate = typeof window !== 'undefined' | |
&& window.setImmediate; | |
var canPost = typeof window !== 'undefined' | |
&& window.postMessage && window.addEventListener | |
; | |
if (canSetImmediate) { | |
return function (f) { return window.setImmediate(f) }; | |
} | |
if (canPost) { | |
var queue = []; | |
window.addEventListener('message', function (ev) { | |
var source = ev.source; | |
if ((source === window || source === null) && ev.data === 'process-tick') { | |
ev.stopPropagation(); | |
if (queue.length > 0) { | |
var fn = queue.shift(); | |
fn(); | |
} | |
} | |
}, true); | |
return function nextTick(fn) { | |
queue.push(fn); | |
window.postMessage('process-tick', '*'); | |
}; | |
} | |
return function nextTick(fn) { | |
setTimeout(fn, 0); | |
}; | |
})(); | |
process.title = 'browser'; | |
process.browser = true; | |
process.env = {}; | |
process.argv = []; | |
function noop() {} | |
process.on = noop; | |
process.addListener = noop; | |
process.once = noop; | |
process.off = noop; | |
process.removeListener = noop; | |
process.removeAllListeners = noop; | |
process.emit = noop; | |
process.binding = function (name) { | |
throw new Error('process.binding is not supported'); | |
} | |
// TODO(shtylman) | |
process.cwd = function () { return '/' }; | |
process.chdir = function (dir) { | |
throw new Error('process.chdir is not supported'); | |
}; | |
},{}],6:[function(require,module,exports){ | |
/* | |
* Author: Alex Gibson | |
* https://github.com/alexgibson/notify.js | |
* License: MIT license | |
*/ | |
(function(global, factory) { | |
if (typeof define === 'function' && define.amd) { | |
// AMD environment | |
define(function() { | |
return factory(global, global.document); | |
}); | |
} else if (typeof module !== 'undefined' && module.exports) { | |
// CommonJS environment | |
module.exports = factory(global, global.document); | |
} else { | |
// Browser environment | |
global.Notify = factory(global, global.document); | |
} | |
} (typeof window !== 'undefined' ? window : this, function (w, d) { | |
'use strict'; | |
function isFunction (item) { | |
return typeof item === 'function'; | |
} | |
function Notify(title, options) { | |
if (typeof title !== 'string') { | |
throw new Error('Notify(): first arg (title) must be a string.'); | |
} | |
this.title = title; | |
this.options = { | |
icon: '', | |
body: '', | |
tag: '', | |
notifyShow: null, | |
notifyClose: null, | |
notifyClick: null, | |
notifyError: null, | |
timeout: null | |
}; | |
this.permission = null; | |
if (!Notify.isSupported) { | |
return; | |
} | |
//User defined options for notification content | |
if (typeof options === 'object') { | |
for (var i in options) { | |
if (options.hasOwnProperty(i)) { | |
this.options[i] = options[i]; | |
} | |
} | |
//callback when notification is displayed | |
if (isFunction(this.options.notifyShow)) { | |
this.onShowCallback = this.options.notifyShow; | |
} | |
//callback when notification is closed | |
if (isFunction(this.options.notifyClose)) { | |
this.onCloseCallback = this.options.notifyClose; | |
} | |
//callback when notification is clicked | |
if (isFunction(this.options.notifyClick)) { | |
this.onClickCallback = this.options.notifyClick; | |
} | |
//callback when notification throws error | |
if (isFunction(this.options.notifyError)) { | |
this.onErrorCallback = this.options.notifyError; | |
} | |
} | |
} | |
// true if the browser supports HTML5 Notification | |
Notify.isSupported = 'Notification' in w; | |
// true if the permission is not granted | |
Notify.needsPermission = !(Notify.isSupported && Notification.permission === 'granted'); | |
// returns current permission level ('granted', 'default', 'denied' or null) | |
Notify.permissionLevel = (Notify.isSupported ? Notification.permission : null); | |
// asks the user for permission to display notifications. Then calls the callback functions is supplied. | |
Notify.requestPermission = function (onPermissionGrantedCallback, onPermissionDeniedCallback) { | |
if (!Notify.isSupported) { | |
return; | |
} | |
w.Notification.requestPermission(function (perm) { | |
switch (perm) { | |
case 'granted': | |
Notify.needsPermission = false; | |
if (isFunction(onPermissionGrantedCallback)) { | |
onPermissionGrantedCallback(); | |
} | |
break; | |
case 'denied': | |
if (isFunction(onPermissionDeniedCallback)) { | |
onPermissionDeniedCallback(); | |
} | |
break; | |
} | |
}); | |
}; | |
Notify.prototype.show = function () { | |
if (!Notify.isSupported) { | |
return; | |
} | |
this.myNotify = new Notification(this.title, { | |
'body': this.options.body, | |
'tag' : this.options.tag, | |
'icon' : this.options.icon | |
}); | |
if (this.options.timeout && !isNaN(this.options.timeout)) { | |
setTimeout(this.close.bind(this), this.options.timeout * 1000); | |
} | |
this.myNotify.addEventListener('show', this, false); | |
this.myNotify.addEventListener('error', this, false); | |
this.myNotify.addEventListener('close', this, false); | |
this.myNotify.addEventListener('click', this, false); | |
}; | |
Notify.prototype.onShowNotification = function (e) { | |
if (this.onShowCallback) { | |
this.onShowCallback(e); | |
} | |
}; | |
Notify.prototype.onCloseNotification = function (e) { | |
if (this.onCloseCallback) { | |
this.onCloseCallback(e); | |
} | |
this.destroy(); | |
}; | |
Notify.prototype.onClickNotification = function (e) { | |
if (this.onClickCallback) { | |
this.onClickCallback(e); | |
} | |
}; | |
Notify.prototype.onErrorNotification = function (e) { | |
if (this.onErrorCallback) { | |
this.onErrorCallback(e); | |
} | |
this.destroy(); | |
}; | |
Notify.prototype.destroy = function () { | |
this.myNotify.removeEventListener('show', this, false); | |
this.myNotify.removeEventListener('error', this, false); | |
this.myNotify.removeEventListener('close', this, false); | |
this.myNotify.removeEventListener('click', this, false); | |
}; | |
Notify.prototype.close = function () { | |
this.myNotify.close(); | |
}; | |
Notify.prototype.handleEvent = function (e) { | |
switch (e.type) { | |
case 'show': | |
this.onShowNotification(e); | |
break; | |
case 'close': | |
this.onCloseNotification(e); | |
break; | |
case 'click': | |
this.onClickNotification(e); | |
break; | |
case 'error': | |
this.onErrorNotification(e); | |
break; | |
} | |
}; | |
return Notify; | |
})); | |
},{}],7:[function(require,module,exports){ | |
;(function(win){ | |
var store = {}, | |
doc = win.document, | |
localStorageName = 'localStorage', | |
scriptTag = 'script', | |
storage | |
store.disabled = false | |
store.version = '1.3.17' | |
store.set = function(key, value) {} | |
store.get = function(key, defaultVal) {} | |
store.has = function(key) { return store.get(key) !== undefined } | |
store.remove = function(key) {} | |
store.clear = function() {} | |
store.transact = function(key, defaultVal, transactionFn) { | |
if (transactionFn == null) { | |
transactionFn = defaultVal | |
defaultVal = null | |
} | |
if (defaultVal == null) { | |
defaultVal = {} | |
} | |
var val = store.get(key, defaultVal) | |
transactionFn(val) | |
store.set(key, val) | |
} | |
store.getAll = function() {} | |
store.forEach = function() {} | |
store.serialize = function(value) { | |
return JSON.stringify(value) | |
} | |
store.deserialize = function(value) { | |
if (typeof value != 'string') { return undefined } | |
try { return JSON.parse(value) } | |
catch(e) { return value || undefined } | |
} | |
// Functions to encapsulate questionable FireFox 3.6.13 behavior | |
// when about.config::dom.storage.enabled === false | |
// See https://github.com/marcuswestin/store.js/issues#issue/13 | |
function isLocalStorageNameSupported() { | |
try { return (localStorageName in win && win[localStorageName]) } | |
catch(err) { return false } | |
} | |
if (isLocalStorageNameSupported()) { | |
storage = win[localStorageName] | |
store.set = function(key, val) { | |
if (val === undefined) { return store.remove(key) } | |
storage.setItem(key, store.serialize(val)) | |
return val | |
} | |
store.get = function(key, defaultVal) { | |
var val = store.deserialize(storage.getItem(key)) | |
return (val === undefined ? defaultVal : val) | |
} | |
store.remove = function(key) { storage.removeItem(key) } | |
store.clear = function() { storage.clear() } | |
store.getAll = function() { | |
var ret = {} | |
store.forEach(function(key, val) { | |
ret[key] = val | |
}) | |
return ret | |
} | |
store.forEach = function(callback) { | |
for (var i=0; i<storage.length; i++) { | |
var key = storage.key(i) | |
callback(key, store.get(key)) | |
} | |
} | |
} else if (doc.documentElement.addBehavior) { | |
var storageOwner, | |
storageContainer | |
// Since #userData storage applies only to specific paths, we need to | |
// somehow link our data to a specific path. We choose /favicon.ico | |
// as a pretty safe option, since all browsers already make a request to | |
// this URL anyway and being a 404 will not hurt us here. We wrap an | |
// iframe pointing to the favicon in an ActiveXObject(htmlfile) object | |
// (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx) | |
// since the iframe access rules appear to allow direct access and | |
// manipulation of the document element, even for a 404 page. This | |
// document can be used instead of the current document (which would | |
// have been limited to the current path) to perform #userData storage. | |
try { | |
storageContainer = new ActiveXObject('htmlfile') | |
storageContainer.open() | |
storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>') | |
storageContainer.close() | |
storageOwner = storageContainer.w.frames[0].document | |
storage = storageOwner.createElement('div') | |
} catch(e) { | |
// somehow ActiveXObject instantiation failed (perhaps some special | |
// security settings or otherwse), fall back to per-path storage | |
storage = doc.createElement('div') | |
storageOwner = doc.body | |
} | |
var withIEStorage = function(storeFunction) { | |
return function() { | |
var args = Array.prototype.slice.call(arguments, 0) | |
args.unshift(storage) | |
// See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx | |
// and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx | |
storageOwner.appendChild(storage) | |
storage.addBehavior('#default#userData') | |
storage.load(localStorageName) | |
var result = storeFunction.apply(store, args) | |
storageOwner.removeChild(storage) | |
return result | |
} | |
} | |
// In IE7, keys cannot start with a digit or contain certain chars. | |
// See https://github.com/marcuswestin/store.js/issues/40 | |
// See https://github.com/marcuswestin/store.js/issues/83 | |
var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g") | |
function ieKeyFix(key) { | |
return key.replace(/^d/, '___$&').replace(forbiddenCharsRegex, '___') | |
} | |
store.set = withIEStorage(function(storage, key, val) { | |
key = ieKeyFix(key) | |
if (val === undefined) { return store.remove(key) } | |
storage.setAttribute(key, store.serialize(val)) | |
storage.save(localStorageName) | |
return val | |
}) | |
store.get = withIEStorage(function(storage, key, defaultVal) { | |
key = ieKeyFix(key) | |
var val = store.deserialize(storage.getAttribute(key)) | |
return (val === undefined ? defaultVal : val) | |
}) | |
store.remove = withIEStorage(function(storage, key) { | |
key = ieKeyFix(key) | |
storage.removeAttribute(key) | |
storage.save(localStorageName) | |
}) | |
store.clear = withIEStorage(function(storage) { | |
var attributes = storage.XMLDocument.documentElement.attributes | |
storage.load(localStorageName) | |
for (var i=0, attr; attr=attributes[i]; i++) { | |
storage.removeAttribute(attr.name) | |
} | |
storage.save(localStorageName) | |
}) | |
store.getAll = function(storage) { | |
var ret = {} | |
store.forEach(function(key, val) { | |
ret[key] = val | |
}) | |
return ret | |
} | |
store.forEach = withIEStorage(function(storage, callback) { | |
var attributes = storage.XMLDocument.documentElement.attributes | |
for (var i=0, attr; attr=attributes[i]; ++i) { | |
callback(attr.name, store.deserialize(storage.getAttribute(attr.name))) | |
} | |
}) | |
} | |
try { | |
var testKey = '__storejs__' | |
store.set(testKey, testKey) | |
if (store.get(testKey) != testKey) { store.disabled = true } | |
store.remove(testKey) | |
} catch(e) { | |
store.disabled = true | |
} | |
store.enabled = !store.disabled | |
if (typeof module != 'undefined' && module.exports && this.module !== module) { module.exports = store } | |
else if (typeof define === 'function' && define.amd) { define(store) } | |
else { win.store = store } | |
})(Function('return this')()); | |
},{}]},{},[1]) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment