Toggle navigation
Toggle navigation
This project
Loading...
Sign in
fe
/
yohobuy-node
·
Commits
Go to a project
GitLab
Go to group
Project
Activity
Files
Commits
Pipelines
0
Builds
0
Graphs
Milestones
Issues
1
Merge Requests
0
Members
Labels
Wiki
Forks
Network
Create a new issue
Download as
Plain Diff
Browse Files
Authored by
htoooth
8 years ago
Commit
5aad2c6d93ff0e6ae6a19abb87f0087d8dbf5a07
2 parents
68e90f6a
15d62e0d
merge user center
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1227 additions
and
50 deletions
apps/home/models/vip-service.js
apps/passport/controllers/captcha.js
apps/passport/data/captcha.json
apps/passport/models/captcha-service.js
apps/passport/router.js
apps/passport/views/action/login/index.hbs
config/cache.js
doraemon/middleware/limiter/index.js
doraemon/middleware/limiter/policies/captcha.js
doraemon/middleware/limiter/rules/qps-limit.js
package.json
public/js/passport/login/index.js
public/js/plugins/captcha.js
public/js/plugins/qrcode.js
public/scss/passport/_login.css
apps/home/models/vip-service.js
View file @
5aad2c6
...
...
@@ -54,7 +54,7 @@ const vipIndex = (uid)=>{
remainDays
:
remainDays
,
doubtLevel
:
isVip
,
commonVip
:
!
isVip
,
morePreferences
:
helpers
.
urlFormat
(
'/help
'
,
{
category_id
:
91
})
morePreferences
:
helpers
.
urlFormat
(
'/help
/detail'
,
{
id
:
7
})
};
return
vip
;
...
...
apps/passport/controllers/captcha.js
View file @
5aad2c6
...
...
@@ -7,11 +7,18 @@
const
captchaService
=
require
(
'../models/captcha-service'
);
const
helpers
=
global
.
yoho
.
helpers
;
const
CAPTCHA
=
'yoho4946abcdef#$%&!@'
;
const
request
=
require
(
'request'
);
const
logger
=
global
.
yoho
.
logger
;
// 对比函数
const
_mustEqual
=
(
req
)
=>
{
return
req
.
session
.
captcha
&&
(
req
.
body
.
verifyCode
===
req
.
session
.
captcha
||
let
result
=
req
.
session
.
captcha
&&
(
req
.
body
.
verifyCode
===
req
.
session
.
captcha
||
req
.
body
.
verifyCode
===
CAPTCHA
);
logger
.
info
(
`
captcha
auth
[
$
{
result
?
'success'
:
'fail'
}]
`
,
`
CLIENT
[
$
{
req
.
body
.
verifyCode
}]
SERVER
[
$
{
req
.
session
.
captcha
}]
`
);
return
result
;
};
// 中间件
...
...
@@ -79,6 +86,20 @@ const generate = (req, res, next) => {
}).
catch
(
next
);
};
// 七牛验证码
const
generateQiniu
=
(
req
,
res
,
next
)
=>
{
captchaService
.
generateCaptcha
().
then
((
result
)
=>
{
req
.
session
.
captcha
=
result
.
data
.
text
;
req
.
session
.
captchaCount
=
0
;
res
.
type
(
'png'
);
if
(
result
.
code
===
200
)
{
request
(
result
.
data
.
images
).
pipe
(
res
);
}
}).
catch
(
next
);
};
// 端到端检查
const
checkAPI
=
(
req
,
res
)
=>
{
let
count
=
req
.
session
.
captchaCount
;
...
...
@@ -110,5 +131,6 @@ module.exports = {
requiredAPI
,
requiredPage
,
generate
,
checkAPI
checkAPI
,
generateQiniu
};
...
...
apps/passport/data/captcha.json
View file @
5aad2c6
This diff could not be displayed because it is too large.
apps/passport/models/captcha-service.js
View file @
5aad2c6
...
...
@@ -5,6 +5,7 @@
'use strict'
;
const
api
=
require
(
'./captcha-api'
);
const
uuid
=
require
(
'uuid'
);
exports
.
generateCaptcha
=
()
=>
{
return
api
.
gen
().
then
((
result
)
=>
{
...
...
@@ -17,7 +18,8 @@ exports.generateCaptcha = () => {
code
:
200
,
data
:
{
text
:
codeStr
,
images
:
`
$
{
result
.
data
.
verifiedGraphicCode
}?
imageView
/
2
/
w
/
240
`
images
:
`
$
{
result
.
data
.
verifiedGraphicCode
}
`
+
`
?
imageView2
/
2
/
w
/
240
/
q
/
70
/
watermark
/
2
/
text
/
$
{
uuid
.
v4
()}
/fontsize/
120
/
dissolve
/
10
`
}
};
}
else
{
...
...
apps/passport/router.js
View file @
5aad2c6
...
...
@@ -201,5 +201,6 @@ router.get('/passport/back/resetSuccess',
router
.
get
(
'/passport/imagesNode'
,
captcha
.
generate
);
router
.
post
(
'/passport/captcha/img'
,
captcha
.
checkAPI
);
router
.
get
(
'/passport/images.png'
,
captcha
.
generateQiniu
);
module
.
exports
=
router
;
...
...
apps/passport/views/action/login/index.hbs
View file @
5aad2c6
...
...
@@ -5,14 +5,14 @@
<div
class=
"content"
>
<ul
class=
"login-ul"
>
<div
class=
"switch-login-type"
data-type=
"DesktopLogin"
>
<div
id=
"device-bg"
class=
"type-mobile-bg"
></div>
<div
class=
"switch-login-type"
data-type=
"MobileLogin"
>
<div
id=
"device-bg"
class=
"type-desktop-bg"
></div>
<div
class=
"type-tip tip-title"
>
<div
id=
"device-tip"
style=
"margin-left: 15px;margin-top: 8px"
>
扫码登录更安全
</div>
<div
id=
"device-tip"
style=
"margin-left: 15px;margin-top: 8px"
>
密码登录在这里
</div>
</div>
</div>
<div
class=
"desktop-login"
>
<div
class=
"desktop-login
hide
"
>
<li
class=
"relative clearfix"
>
<h2
class=
"title"
>
会员登录
</h2>
<span
id=
"country-code"
class=
"country-code right"
>
...
...
@@ -121,7 +121,7 @@
</div>
<div
class=
"mobile-login
hide
"
>
<div
class=
"mobile-login"
>
<li
class=
"relative clearfix center qrcode-login-title"
>
<div>
...
...
config/cache.js
View file @
5aad2c6
...
...
@@ -15,7 +15,7 @@ const cachePage = {
// 商品详情页
// '/product/\\/pro_([\\d]+)_([\\d]+)\\/(.*)/': 30 * MINUTE,
'/product/\\/p([\\d]+)(.*)/'
:
30
*
MINUTE
,
'/product/\\/p([\\d]+)(.*)/'
:
5
*
MINUTE
,
// 逛
'/guang/'
:
1
*
MINUTE
,
...
...
doraemon/middleware/limiter/index.js
View file @
5aad2c6
...
...
@@ -10,9 +10,9 @@ const captchaPolicy = require('./policies/captcha');
const
reporterPolicy
=
require
(
'./policies/reporter'
);
const
IP_WHITE_LIST
=
[
// '106.38.38.146',
// '218.94.75.58'
'106.38.38.146'
,
'218.94.75.58'
,
'218.94.75.50'
];
const
limiter
=
(
rule
,
policy
,
context
)
=>
{
...
...
@@ -20,15 +20,22 @@ const limiter = (rule, policy, context) => {
};
module
.
exports
=
(
req
,
res
,
next
)
=>
{
let
remoteIp
=
req
.
get
(
'X-Forwarded-For'
)
||
req
.
connection
.
remoteAddress
;
logger
.
debug
(
'request remote ip: '
,
remoteIp
);
let
remoteIp
=
req
.
get
(
'X-Forwarded-For'
)
||
req
.
get
(
'X-Real-IP'
)
||
''
;
if
(
remoteIp
.
indexOf
(
','
)
>
0
)
{
let
arr
=
remoteIp
.
split
(
','
);
remoteIp
=
arr
[
0
];
remoteIp
=
arr
[
arr
.
length
-
1
];
}
remoteIp
=
_
.
trim
(
remoteIp
);
if
(
_
.
startsWith
(
remoteIp
,
'10.66.'
))
{
remoteIp
=
req
.
get
(
'X-Real-IP'
);
}
logger
.
info
(
'request remote ip: '
,
remoteIp
);
const
excluded
=
_
.
includes
(
IP_WHITE_LIST
,
remoteIp
);
const
enabled
=
!
_
.
get
(
req
.
app
.
locals
,
'pc.sys.noLimiter'
);
...
...
doraemon/middleware/limiter/policies/captcha.js
View file @
5aad2c6
...
...
@@ -6,6 +6,7 @@ const _ = require('lodash');
const
WHITE_LIST
=
[
'/3party/check'
,
'/passport/imagesNode'
,
'/passport/images.png'
,
'/passport/cert/headerTip'
];
...
...
@@ -18,6 +19,10 @@ module.exports = (req, res, next) => {
return
next
();
}
if
(
res
.
statusCode
==
403
)
{
return
res
.
end
();
}
if
(
req
.
xhr
)
{
return
res
.
json
({
code
:
400
,
...
...
doraemon/middleware/limiter/rules/qps-limit.js
View file @
5aad2c6
...
...
@@ -56,7 +56,10 @@ module.exports = (limiter, policy) => {
return
Promise
.
resolve
(
true
);
}
if
(
result
>
MAX_QPS
)
{
// 判断 qps
if
(
result
===
9999
)
{
res
.
statusCode
=
403
;
return
Promise
.
resolve
(
policy
);
}
else
if
(
result
>
MAX_QPS
)
{
// 判断 qps
cache
.
touch
(
key
,
ONE_DAY
);
logger
.
debug
(
'req limit'
,
key
);
...
...
@@ -67,7 +70,7 @@ module.exports = (limiter, policy) => {
}
}
else
{
cache
.
setAsync
(
key
,
1
,
60
);
// 设置key,1m失效
cache
.
setAsync
(
key
,
1
,
60
);
// 设置key,1m失效
return
Promise
.
resolve
(
true
);
}
});
...
...
package.json
View file @
5aad2c6
{
"name"
:
"yohobuy-node"
,
"version"
:
"5.4.2
0
"
,
"version"
:
"5.4.2
5
"
,
"private"
:
true
,
"description"
:
"A New Yohobuy Project With Express"
,
"repository"
:
{
...
...
@@ -57,6 +57,7 @@
"passport-sina"
:
"^0.1.0"
,
"passport-strategy"
:
"1.x.x"
,
"passport-weixin"
:
"^0.1.0"
,
"request"
:
"^2.81.0"
,
"request-ip"
:
"^1.2.2"
,
"request-promise"
:
"^3.0.0"
,
"serve-favicon"
:
"^2.3.0"
,
...
...
public/js/passport/login/index.js
View file @
5aad2c6
...
...
@@ -32,7 +32,8 @@
*/
var
$
=
require
(
'yoho-jquery'
),
Captcha
=
require
(
'../../plugins/captcha'
);
Captcha
=
require
(
'../../plugins/captcha'
),
QRCode
=
require
(
'../../plugins/qrcode'
);
// 密码输入帐号
var
$accountInput1
=
$
(
'#account1'
),
...
...
@@ -98,7 +99,12 @@ var $accountInput1 = $('#account1'),
},
$qrCodeContainer
=
$
(
'#qrcode-container'
),
$qrCodeOverLayer
=
$
(
'#qrcode-overlay'
),
pollingQrCodeTimer
;
pollingQrCodeTimer
,
qrCode
=
new
QRCode
(
$qrCodeContainer
.
get
(
0
),
{
width
:
140
,
height
:
140
,
correctLevel
:
1
});
// 提示
var
$accountTip1
=
$accountInput1
.
siblings
(
'.err-tip'
),
...
...
@@ -320,7 +326,6 @@ refreshSmsImgCallBack.add(function() {
/* 加载自定义库 */
/** ************************************************************************/
require
(
'yoho-jquery-qrcode'
);
require
(
'yoho-jquery-placeholder'
);
require
(
'../../simple-header'
);
require
(
'../../common'
);
// yas
...
...
@@ -653,7 +658,7 @@ function validateSmsCaptchaImg() {
}
function
refreshSmsCaptchaImg
()
{
$
.
sleep
(
10
00
).
then
(
function
()
{
$
.
sleep
(
5
00
).
then
(
function
()
{
smsCaptchaImg
.
refresh
();
});
}
...
...
@@ -663,12 +668,7 @@ function refreshSmsCaptchaImg() {
/** ************************************************************************/
function
drawQrCode
(
qrcode
)
{
$qrCodeContainer
.
empty
().
qrcode
({
render
:
'table'
,
size
:
140
,
text
:
qrcode
});
qrCode
.
clear
().
makeCode
(
qrcode
);
$qrCodeHideInput
.
val
(
qrcode
);
}
...
...
@@ -1119,7 +1119,7 @@ $('input.va').on('keypress', function(e) {
/* 初始化 */
/** ************************************************************************/
// 初始化为:
桌面
登录
// 初始化为:
二维码
登录
$deviceSwitcher
.
triggerHandler
(
'click'
);
// 只带账户名的页面,密码输入获得焦点
...
...
public/js/plugins/captcha.js
View file @
5aad2c6
...
...
@@ -5,7 +5,7 @@
var
Captcha
=
function
(
container
,
options
)
{
var
optionDefault
=
{
template
:
require
(
'hbs/common/captcha.hbs'
),
refreshURI
:
'/passport/images
Node
'
,
refreshURI
:
'/passport/images
.png
'
,
checkURI
:
'/passport/captcha/img'
};
...
...
@@ -92,7 +92,7 @@ Captcha.prototype = {
*/
refresh
:
function
()
{
var
self
=
this
;
var
uri
=
this
.
refreshURI
;
var
uri
=
this
.
refreshURI
+
'?t='
+
$
.
now
()
;
if
(
self
.
running
)
{
return
$
.
Deferred
().
reject
().
promise
();
// eslint-disable-line
...
...
@@ -100,25 +100,15 @@ Captcha.prototype = {
self
.
running
=
true
;
return
$
.
get
(
uri
)
.
done
(
function
(
result
)
{
if
(
result
.
code
!==
200
)
{
return
self
.
showTip
();
}
var
src
=
result
.
data
.
images
;
// eslint-disable-line
self
.
render
({
images
:
uri
});
self
.
render
({
images
:
src
});
self
.
hideTip
();
self
.
refreshCb
&&
self
.
refreshCb
();
self
.
running
=
false
;
self
.
hideTip
();
self
.
refreshCb
&&
self
.
refreshCb
();
})
.
always
(
function
()
{
self
.
running
=
false
;
});
return
$
.
Deferred
().
resolve
().
promise
();
// eslint-disable-line
},
onRefresh
:
function
(
cb
)
{
...
...
public/js/plugins/qrcode.js
0 → 100644
View file @
5aad2c6
/* eslint-disable */
/**
* @fileoverview
* - Using the 'QRCode for Javascript library'
* - Fixed dataset of 'QRCode for Javascript library' for support full-spec.
* - this library has no dependencies.
*
* @author davidshimjs
* @see <a href="http://www.d-project.com/" target="_blank">http://www.d-project.com/</a>
* @see <a href="http://jeromeetienne.github.com/jquery-qrcode/" target="_blank">http://jeromeetienne.github.com/jquery-qrcode/</a>
*/
module
.
exports
=
(
function
()
{
//---------------------------------------------------------------------
// QRCode for JavaScript
//
// Copyright (c) 2009 Kazuhiko Arase
//
// URL: http://www.d-project.com/
//
// Licensed under the MIT license:
// http://www.opensource.org/licenses/mit-license.php
//
// The word "QR Code" is registered trademark of
// DENSO WAVE INCORPORATED
// http://www.denso-wave.com/qrcode/faqpatent-e.html
//
//---------------------------------------------------------------------
function
QR8bitByte
(
data
)
{
this
.
mode
=
QRMode
.
MODE_8BIT_BYTE
;
this
.
data
=
data
;
this
.
parsedData
=
[];
// Added to support UTF-8 Characters
for
(
var
i
=
0
,
l
=
this
.
data
.
length
;
i
<
l
;
i
++
)
{
var
byteArray
=
[];
var
code
=
this
.
data
.
charCodeAt
(
i
);
if
(
code
>
0x10000
)
{
byteArray
[
0
]
=
0xF0
|
((
code
&
0x1C0000
)
>>>
18
);
byteArray
[
1
]
=
0x80
|
((
code
&
0x3F000
)
>>>
12
);
byteArray
[
2
]
=
0x80
|
((
code
&
0xFC0
)
>>>
6
);
byteArray
[
3
]
=
0x80
|
(
code
&
0x3F
);
}
else
if
(
code
>
0x800
)
{
byteArray
[
0
]
=
0xE0
|
((
code
&
0xF000
)
>>>
12
);
byteArray
[
1
]
=
0x80
|
((
code
&
0xFC0
)
>>>
6
);
byteArray
[
2
]
=
0x80
|
(
code
&
0x3F
);
}
else
if
(
code
>
0x80
)
{
byteArray
[
0
]
=
0xC0
|
((
code
&
0x7C0
)
>>>
6
);
byteArray
[
1
]
=
0x80
|
(
code
&
0x3F
);
}
else
{
byteArray
[
0
]
=
code
;
}
this
.
parsedData
.
push
(
byteArray
);
}
this
.
parsedData
=
Array
.
prototype
.
concat
.
apply
([],
this
.
parsedData
);
if
(
this
.
parsedData
.
length
!=
this
.
data
.
length
)
{
this
.
parsedData
.
unshift
(
191
);
this
.
parsedData
.
unshift
(
187
);
this
.
parsedData
.
unshift
(
239
);
}
}
QR8bitByte
.
prototype
=
{
getLength
:
function
(
buffer
)
{
return
this
.
parsedData
.
length
;
},
write
:
function
(
buffer
)
{
for
(
var
i
=
0
,
l
=
this
.
parsedData
.
length
;
i
<
l
;
i
++
)
{
buffer
.
put
(
this
.
parsedData
[
i
],
8
);
}
}
};
function
QRCodeModel
(
typeNumber
,
errorCorrectLevel
)
{
this
.
typeNumber
=
typeNumber
;
this
.
errorCorrectLevel
=
errorCorrectLevel
;
this
.
modules
=
null
;
this
.
moduleCount
=
0
;
this
.
dataCache
=
null
;
this
.
dataList
=
[];
}
QRCodeModel
.
prototype
=
{
addData
:
function
(
data
)
{
var
newData
=
new
QR8bitByte
(
data
);
this
.
dataList
.
push
(
newData
);
this
.
dataCache
=
null
;
},
isDark
:
function
(
row
,
col
)
{
if
(
row
<
0
||
this
.
moduleCount
<=
row
||
col
<
0
||
this
.
moduleCount
<=
col
)
{
throw
new
Error
(
row
+
","
+
col
);
}
return
this
.
modules
[
row
][
col
];
},
getModuleCount
:
function
()
{
return
this
.
moduleCount
;
},
make
:
function
()
{
this
.
makeImpl
(
false
,
this
.
getBestMaskPattern
());
},
makeImpl
:
function
(
test
,
maskPattern
)
{
this
.
moduleCount
=
this
.
typeNumber
*
4
+
17
;
this
.
modules
=
new
Array
(
this
.
moduleCount
);
for
(
var
row
=
0
;
row
<
this
.
moduleCount
;
row
++
)
{
this
.
modules
[
row
]
=
new
Array
(
this
.
moduleCount
);
for
(
var
col
=
0
;
col
<
this
.
moduleCount
;
col
++
)
{
this
.
modules
[
row
][
col
]
=
null
;
}
}
this
.
setupPositionProbePattern
(
0
,
0
);
this
.
setupPositionProbePattern
(
this
.
moduleCount
-
7
,
0
);
this
.
setupPositionProbePattern
(
0
,
this
.
moduleCount
-
7
);
this
.
setupPositionAdjustPattern
();
this
.
setupTimingPattern
();
this
.
setupTypeInfo
(
test
,
maskPattern
);
if
(
this
.
typeNumber
>=
7
)
{
this
.
setupTypeNumber
(
test
);
}
if
(
this
.
dataCache
==
null
)
{
this
.
dataCache
=
QRCodeModel
.
createData
(
this
.
typeNumber
,
this
.
errorCorrectLevel
,
this
.
dataList
);
}
this
.
mapData
(
this
.
dataCache
,
maskPattern
);
},
setupPositionProbePattern
:
function
(
row
,
col
)
{
for
(
var
r
=
-
1
;
r
<=
7
;
r
++
)
{
if
(
row
+
r
<=
-
1
||
this
.
moduleCount
<=
row
+
r
)
continue
;
for
(
var
c
=
-
1
;
c
<=
7
;
c
++
)
{
if
(
col
+
c
<=
-
1
||
this
.
moduleCount
<=
col
+
c
)
continue
;
if
((
0
<=
r
&&
r
<=
6
&&
(
c
==
0
||
c
==
6
))
||
(
0
<=
c
&&
c
<=
6
&&
(
r
==
0
||
r
==
6
))
||
(
2
<=
r
&&
r
<=
4
&&
2
<=
c
&&
c
<=
4
))
{
this
.
modules
[
row
+
r
][
col
+
c
]
=
true
;
}
else
{
this
.
modules
[
row
+
r
][
col
+
c
]
=
false
;
}
}
}
},
getBestMaskPattern
:
function
()
{
var
minLostPoint
=
0
;
var
pattern
=
0
;
for
(
var
i
=
0
;
i
<
8
;
i
++
)
{
this
.
makeImpl
(
true
,
i
);
var
lostPoint
=
QRUtil
.
getLostPoint
(
this
);
if
(
i
==
0
||
minLostPoint
>
lostPoint
)
{
minLostPoint
=
lostPoint
;
pattern
=
i
;
}
}
return
pattern
;
},
createMovieClip
:
function
(
target_mc
,
instance_name
,
depth
)
{
var
qr_mc
=
target_mc
.
createEmptyMovieClip
(
instance_name
,
depth
);
var
cs
=
1
;
this
.
make
();
for
(
var
row
=
0
;
row
<
this
.
modules
.
length
;
row
++
)
{
var
y
=
row
*
cs
;
for
(
var
col
=
0
;
col
<
this
.
modules
[
row
].
length
;
col
++
)
{
var
x
=
col
*
cs
;
var
dark
=
this
.
modules
[
row
][
col
];
if
(
dark
)
{
qr_mc
.
beginFill
(
0
,
100
);
qr_mc
.
moveTo
(
x
,
y
);
qr_mc
.
lineTo
(
x
+
cs
,
y
);
qr_mc
.
lineTo
(
x
+
cs
,
y
+
cs
);
qr_mc
.
lineTo
(
x
,
y
+
cs
);
qr_mc
.
endFill
();
}
}
}
return
qr_mc
;
},
setupTimingPattern
:
function
()
{
for
(
var
r
=
8
;
r
<
this
.
moduleCount
-
8
;
r
++
)
{
if
(
this
.
modules
[
r
][
6
]
!=
null
)
{
continue
;
}
this
.
modules
[
r
][
6
]
=
(
r
%
2
==
0
);
}
for
(
var
c
=
8
;
c
<
this
.
moduleCount
-
8
;
c
++
)
{
if
(
this
.
modules
[
6
][
c
]
!=
null
)
{
continue
;
}
this
.
modules
[
6
][
c
]
=
(
c
%
2
==
0
);
}
},
setupPositionAdjustPattern
:
function
()
{
var
pos
=
QRUtil
.
getPatternPosition
(
this
.
typeNumber
);
for
(
var
i
=
0
;
i
<
pos
.
length
;
i
++
)
{
for
(
var
j
=
0
;
j
<
pos
.
length
;
j
++
)
{
var
row
=
pos
[
i
];
var
col
=
pos
[
j
];
if
(
this
.
modules
[
row
][
col
]
!=
null
)
{
continue
;
}
for
(
var
r
=
-
2
;
r
<=
2
;
r
++
)
{
for
(
var
c
=
-
2
;
c
<=
2
;
c
++
)
{
if
(
r
==
-
2
||
r
==
2
||
c
==
-
2
||
c
==
2
||
(
r
==
0
&&
c
==
0
))
{
this
.
modules
[
row
+
r
][
col
+
c
]
=
true
;
}
else
{
this
.
modules
[
row
+
r
][
col
+
c
]
=
false
;
}
}
}
}
}
},
setupTypeNumber
:
function
(
test
)
{
var
bits
=
QRUtil
.
getBCHTypeNumber
(
this
.
typeNumber
);
for
(
var
i
=
0
;
i
<
18
;
i
++
)
{
var
mod
=
(
!
test
&&
((
bits
>>
i
)
&
1
)
==
1
);
this
.
modules
[
Math
.
floor
(
i
/
3
)][
i
%
3
+
this
.
moduleCount
-
8
-
3
]
=
mod
;
}
for
(
var
i
=
0
;
i
<
18
;
i
++
)
{
var
mod
=
(
!
test
&&
((
bits
>>
i
)
&
1
)
==
1
);
this
.
modules
[
i
%
3
+
this
.
moduleCount
-
8
-
3
][
Math
.
floor
(
i
/
3
)]
=
mod
;
}
},
setupTypeInfo
:
function
(
test
,
maskPattern
)
{
var
data
=
(
this
.
errorCorrectLevel
<<
3
)
|
maskPattern
;
var
bits
=
QRUtil
.
getBCHTypeInfo
(
data
);
for
(
var
i
=
0
;
i
<
15
;
i
++
)
{
var
mod
=
(
!
test
&&
((
bits
>>
i
)
&
1
)
==
1
);
if
(
i
<
6
)
{
this
.
modules
[
i
][
8
]
=
mod
;
}
else
if
(
i
<
8
)
{
this
.
modules
[
i
+
1
][
8
]
=
mod
;
}
else
{
this
.
modules
[
this
.
moduleCount
-
15
+
i
][
8
]
=
mod
;
}
}
for
(
var
i
=
0
;
i
<
15
;
i
++
)
{
var
mod
=
(
!
test
&&
((
bits
>>
i
)
&
1
)
==
1
);
if
(
i
<
8
)
{
this
.
modules
[
8
][
this
.
moduleCount
-
i
-
1
]
=
mod
;
}
else
if
(
i
<
9
)
{
this
.
modules
[
8
][
15
-
i
-
1
+
1
]
=
mod
;
}
else
{
this
.
modules
[
8
][
15
-
i
-
1
]
=
mod
;
}
}
this
.
modules
[
this
.
moduleCount
-
8
][
8
]
=
(
!
test
);
},
mapData
:
function
(
data
,
maskPattern
)
{
var
inc
=
-
1
;
var
row
=
this
.
moduleCount
-
1
;
var
bitIndex
=
7
;
var
byteIndex
=
0
;
for
(
var
col
=
this
.
moduleCount
-
1
;
col
>
0
;
col
-=
2
)
{
if
(
col
==
6
)
col
--
;
while
(
true
)
{
for
(
var
c
=
0
;
c
<
2
;
c
++
)
{
if
(
this
.
modules
[
row
][
col
-
c
]
==
null
)
{
var
dark
=
false
;
if
(
byteIndex
<
data
.
length
)
{
dark
=
(((
data
[
byteIndex
]
>>>
bitIndex
)
&
1
)
==
1
);
}
var
mask
=
QRUtil
.
getMask
(
maskPattern
,
row
,
col
-
c
);
if
(
mask
)
{
dark
=
!
dark
;
}
this
.
modules
[
row
][
col
-
c
]
=
dark
;
bitIndex
--
;
if
(
bitIndex
==
-
1
)
{
byteIndex
++
;
bitIndex
=
7
;
}
}
}
row
+=
inc
;
if
(
row
<
0
||
this
.
moduleCount
<=
row
)
{
row
-=
inc
;
inc
=
-
inc
;
break
;
}
}
}
}
};
QRCodeModel
.
PAD0
=
0xEC
;
QRCodeModel
.
PAD1
=
0x11
;
QRCodeModel
.
createData
=
function
(
typeNumber
,
errorCorrectLevel
,
dataList
)
{
var
rsBlocks
=
QRRSBlock
.
getRSBlocks
(
typeNumber
,
errorCorrectLevel
);
var
buffer
=
new
QRBitBuffer
();
for
(
var
i
=
0
;
i
<
dataList
.
length
;
i
++
)
{
var
data
=
dataList
[
i
];
buffer
.
put
(
data
.
mode
,
4
);
buffer
.
put
(
data
.
getLength
(),
QRUtil
.
getLengthInBits
(
data
.
mode
,
typeNumber
));
data
.
write
(
buffer
);
}
var
totalDataCount
=
0
;
for
(
var
i
=
0
;
i
<
rsBlocks
.
length
;
i
++
)
{
totalDataCount
+=
rsBlocks
[
i
].
dataCount
;
}
if
(
buffer
.
getLengthInBits
()
>
totalDataCount
*
8
)
{
throw
new
Error
(
"code length overflow. ("
+
buffer
.
getLengthInBits
()
+
">"
+
totalDataCount
*
8
+
")"
);
}
if
(
buffer
.
getLengthInBits
()
+
4
<=
totalDataCount
*
8
)
{
buffer
.
put
(
0
,
4
);
}
while
(
buffer
.
getLengthInBits
()
%
8
!=
0
)
{
buffer
.
putBit
(
false
);
}
while
(
true
)
{
if
(
buffer
.
getLengthInBits
()
>=
totalDataCount
*
8
)
{
break
;
}
buffer
.
put
(
QRCodeModel
.
PAD0
,
8
);
if
(
buffer
.
getLengthInBits
()
>=
totalDataCount
*
8
)
{
break
;
}
buffer
.
put
(
QRCodeModel
.
PAD1
,
8
);
}
return
QRCodeModel
.
createBytes
(
buffer
,
rsBlocks
);
};
QRCodeModel
.
createBytes
=
function
(
buffer
,
rsBlocks
)
{
var
offset
=
0
;
var
maxDcCount
=
0
;
var
maxEcCount
=
0
;
var
dcdata
=
new
Array
(
rsBlocks
.
length
);
var
ecdata
=
new
Array
(
rsBlocks
.
length
);
for
(
var
r
=
0
;
r
<
rsBlocks
.
length
;
r
++
)
{
var
dcCount
=
rsBlocks
[
r
].
dataCount
;
var
ecCount
=
rsBlocks
[
r
].
totalCount
-
dcCount
;
maxDcCount
=
Math
.
max
(
maxDcCount
,
dcCount
);
maxEcCount
=
Math
.
max
(
maxEcCount
,
ecCount
);
dcdata
[
r
]
=
new
Array
(
dcCount
);
for
(
var
i
=
0
;
i
<
dcdata
[
r
].
length
;
i
++
)
{
dcdata
[
r
][
i
]
=
0xff
&
buffer
.
buffer
[
i
+
offset
];
}
offset
+=
dcCount
;
var
rsPoly
=
QRUtil
.
getErrorCorrectPolynomial
(
ecCount
);
var
rawPoly
=
new
QRPolynomial
(
dcdata
[
r
],
rsPoly
.
getLength
()
-
1
);
var
modPoly
=
rawPoly
.
mod
(
rsPoly
);
ecdata
[
r
]
=
new
Array
(
rsPoly
.
getLength
()
-
1
);
for
(
var
i
=
0
;
i
<
ecdata
[
r
].
length
;
i
++
)
{
var
modIndex
=
i
+
modPoly
.
getLength
()
-
ecdata
[
r
].
length
;
ecdata
[
r
][
i
]
=
(
modIndex
>=
0
)
?
modPoly
.
get
(
modIndex
)
:
0
;
}
}
var
totalCodeCount
=
0
;
for
(
var
i
=
0
;
i
<
rsBlocks
.
length
;
i
++
)
{
totalCodeCount
+=
rsBlocks
[
i
].
totalCount
;
}
var
data
=
new
Array
(
totalCodeCount
);
var
index
=
0
;
for
(
var
i
=
0
;
i
<
maxDcCount
;
i
++
)
{
for
(
var
r
=
0
;
r
<
rsBlocks
.
length
;
r
++
)
{
if
(
i
<
dcdata
[
r
].
length
)
{
data
[
index
++
]
=
dcdata
[
r
][
i
];
}
}
}
for
(
var
i
=
0
;
i
<
maxEcCount
;
i
++
)
{
for
(
var
r
=
0
;
r
<
rsBlocks
.
length
;
r
++
)
{
if
(
i
<
ecdata
[
r
].
length
)
{
data
[
index
++
]
=
ecdata
[
r
][
i
];
}
}
}
return
data
;
};
var
QRMode
=
{
MODE_NUMBER
:
1
<<
0
,
MODE_ALPHA_NUM
:
1
<<
1
,
MODE_8BIT_BYTE
:
1
<<
2
,
MODE_KANJI
:
1
<<
3
};
var
QRErrorCorrectLevel
=
{
L
:
1
,
M
:
0
,
Q
:
3
,
H
:
2
};
var
QRMaskPattern
=
{
PATTERN000
:
0
,
PATTERN001
:
1
,
PATTERN010
:
2
,
PATTERN011
:
3
,
PATTERN100
:
4
,
PATTERN101
:
5
,
PATTERN110
:
6
,
PATTERN111
:
7
};
var
QRUtil
=
{
PATTERN_POSITION_TABLE
:
[[],
[
6
,
18
],
[
6
,
22
],
[
6
,
26
],
[
6
,
30
],
[
6
,
34
],
[
6
,
22
,
38
],
[
6
,
24
,
42
],
[
6
,
26
,
46
],
[
6
,
28
,
50
],
[
6
,
30
,
54
],
[
6
,
32
,
58
],
[
6
,
34
,
62
],
[
6
,
26
,
46
,
66
],
[
6
,
26
,
48
,
70
],
[
6
,
26
,
50
,
74
],
[
6
,
30
,
54
,
78
],
[
6
,
30
,
56
,
82
],
[
6
,
30
,
58
,
86
],
[
6
,
34
,
62
,
90
],
[
6
,
28
,
50
,
72
,
94
],
[
6
,
26
,
50
,
74
,
98
],
[
6
,
30
,
54
,
78
,
102
],
[
6
,
28
,
54
,
80
,
106
],
[
6
,
32
,
58
,
84
,
110
],
[
6
,
30
,
58
,
86
,
114
],
[
6
,
34
,
62
,
90
,
118
],
[
6
,
26
,
50
,
74
,
98
,
122
],
[
6
,
30
,
54
,
78
,
102
,
126
],
[
6
,
26
,
52
,
78
,
104
,
130
],
[
6
,
30
,
56
,
82
,
108
,
134
],
[
6
,
34
,
60
,
86
,
112
,
138
],
[
6
,
30
,
58
,
86
,
114
,
142
],
[
6
,
34
,
62
,
90
,
118
,
146
],
[
6
,
30
,
54
,
78
,
102
,
126
,
150
],
[
6
,
24
,
50
,
76
,
102
,
128
,
154
],
[
6
,
28
,
54
,
80
,
106
,
132
,
158
],
[
6
,
32
,
58
,
84
,
110
,
136
,
162
],
[
6
,
26
,
54
,
82
,
110
,
138
,
166
],
[
6
,
30
,
58
,
86
,
114
,
142
,
170
]],
G15
:
(
1
<<
10
)
|
(
1
<<
8
)
|
(
1
<<
5
)
|
(
1
<<
4
)
|
(
1
<<
2
)
|
(
1
<<
1
)
|
(
1
<<
0
),
G18
:
(
1
<<
12
)
|
(
1
<<
11
)
|
(
1
<<
10
)
|
(
1
<<
9
)
|
(
1
<<
8
)
|
(
1
<<
5
)
|
(
1
<<
2
)
|
(
1
<<
0
),
G15_MASK
:
(
1
<<
14
)
|
(
1
<<
12
)
|
(
1
<<
10
)
|
(
1
<<
4
)
|
(
1
<<
1
),
getBCHTypeInfo
:
function
(
data
)
{
var
d
=
data
<<
10
;
while
(
QRUtil
.
getBCHDigit
(
d
)
-
QRUtil
.
getBCHDigit
(
QRUtil
.
G15
)
>=
0
)
{
d
^=
(
QRUtil
.
G15
<<
(
QRUtil
.
getBCHDigit
(
d
)
-
QRUtil
.
getBCHDigit
(
QRUtil
.
G15
)));
}
return
((
data
<<
10
)
|
d
)
^
QRUtil
.
G15_MASK
;
},
getBCHTypeNumber
:
function
(
data
)
{
var
d
=
data
<<
12
;
while
(
QRUtil
.
getBCHDigit
(
d
)
-
QRUtil
.
getBCHDigit
(
QRUtil
.
G18
)
>=
0
)
{
d
^=
(
QRUtil
.
G18
<<
(
QRUtil
.
getBCHDigit
(
d
)
-
QRUtil
.
getBCHDigit
(
QRUtil
.
G18
)));
}
return
(
data
<<
12
)
|
d
;
},
getBCHDigit
:
function
(
data
)
{
var
digit
=
0
;
while
(
data
!=
0
)
{
digit
++
;
data
>>>=
1
;
}
return
digit
;
},
getPatternPosition
:
function
(
typeNumber
)
{
return
QRUtil
.
PATTERN_POSITION_TABLE
[
typeNumber
-
1
];
},
getMask
:
function
(
maskPattern
,
i
,
j
)
{
switch
(
maskPattern
)
{
case
QRMaskPattern
.
PATTERN000
:
return
(
i
+
j
)
%
2
==
0
;
case
QRMaskPattern
.
PATTERN001
:
return
i
%
2
==
0
;
case
QRMaskPattern
.
PATTERN010
:
return
j
%
3
==
0
;
case
QRMaskPattern
.
PATTERN011
:
return
(
i
+
j
)
%
3
==
0
;
case
QRMaskPattern
.
PATTERN100
:
return
(
Math
.
floor
(
i
/
2
)
+
Math
.
floor
(
j
/
3
))
%
2
==
0
;
case
QRMaskPattern
.
PATTERN101
:
return
(
i
*
j
)
%
2
+
(
i
*
j
)
%
3
==
0
;
case
QRMaskPattern
.
PATTERN110
:
return
((
i
*
j
)
%
2
+
(
i
*
j
)
%
3
)
%
2
==
0
;
case
QRMaskPattern
.
PATTERN111
:
return
((
i
*
j
)
%
3
+
(
i
+
j
)
%
2
)
%
2
==
0
;
default
:
throw
new
Error
(
"bad maskPattern:"
+
maskPattern
);
}
},
getErrorCorrectPolynomial
:
function
(
errorCorrectLength
)
{
var
a
=
new
QRPolynomial
([
1
],
0
);
for
(
var
i
=
0
;
i
<
errorCorrectLength
;
i
++
)
{
a
=
a
.
multiply
(
new
QRPolynomial
([
1
,
QRMath
.
gexp
(
i
)],
0
));
}
return
a
;
},
getLengthInBits
:
function
(
mode
,
type
)
{
if
(
1
<=
type
&&
type
<
10
)
{
switch
(
mode
)
{
case
QRMode
.
MODE_NUMBER
:
return
10
;
case
QRMode
.
MODE_ALPHA_NUM
:
return
9
;
case
QRMode
.
MODE_8BIT_BYTE
:
return
8
;
case
QRMode
.
MODE_KANJI
:
return
8
;
default
:
throw
new
Error
(
"mode:"
+
mode
);
}
}
else
if
(
type
<
27
)
{
switch
(
mode
)
{
case
QRMode
.
MODE_NUMBER
:
return
12
;
case
QRMode
.
MODE_ALPHA_NUM
:
return
11
;
case
QRMode
.
MODE_8BIT_BYTE
:
return
16
;
case
QRMode
.
MODE_KANJI
:
return
10
;
default
:
throw
new
Error
(
"mode:"
+
mode
);
}
}
else
if
(
type
<
41
)
{
switch
(
mode
)
{
case
QRMode
.
MODE_NUMBER
:
return
14
;
case
QRMode
.
MODE_ALPHA_NUM
:
return
13
;
case
QRMode
.
MODE_8BIT_BYTE
:
return
16
;
case
QRMode
.
MODE_KANJI
:
return
12
;
default
:
throw
new
Error
(
"mode:"
+
mode
);
}
}
else
{
throw
new
Error
(
"type:"
+
type
);
}
},
getLostPoint
:
function
(
qrCode
)
{
var
moduleCount
=
qrCode
.
getModuleCount
();
var
lostPoint
=
0
;
for
(
var
row
=
0
;
row
<
moduleCount
;
row
++
)
{
for
(
var
col
=
0
;
col
<
moduleCount
;
col
++
)
{
var
sameCount
=
0
;
var
dark
=
qrCode
.
isDark
(
row
,
col
);
for
(
var
r
=
-
1
;
r
<=
1
;
r
++
)
{
if
(
row
+
r
<
0
||
moduleCount
<=
row
+
r
)
{
continue
;
}
for
(
var
c
=
-
1
;
c
<=
1
;
c
++
)
{
if
(
col
+
c
<
0
||
moduleCount
<=
col
+
c
)
{
continue
;
}
if
(
r
==
0
&&
c
==
0
)
{
continue
;
}
if
(
dark
==
qrCode
.
isDark
(
row
+
r
,
col
+
c
))
{
sameCount
++
;
}
}
}
if
(
sameCount
>
5
)
{
lostPoint
+=
(
3
+
sameCount
-
5
);
}
}
}
for
(
var
row
=
0
;
row
<
moduleCount
-
1
;
row
++
)
{
for
(
var
col
=
0
;
col
<
moduleCount
-
1
;
col
++
)
{
var
count
=
0
;
if
(
qrCode
.
isDark
(
row
,
col
))
count
++
;
if
(
qrCode
.
isDark
(
row
+
1
,
col
))
count
++
;
if
(
qrCode
.
isDark
(
row
,
col
+
1
))
count
++
;
if
(
qrCode
.
isDark
(
row
+
1
,
col
+
1
))
count
++
;
if
(
count
==
0
||
count
==
4
)
{
lostPoint
+=
3
;
}
}
}
for
(
var
row
=
0
;
row
<
moduleCount
;
row
++
)
{
for
(
var
col
=
0
;
col
<
moduleCount
-
6
;
col
++
)
{
if
(
qrCode
.
isDark
(
row
,
col
)
&&
!
qrCode
.
isDark
(
row
,
col
+
1
)
&&
qrCode
.
isDark
(
row
,
col
+
2
)
&&
qrCode
.
isDark
(
row
,
col
+
3
)
&&
qrCode
.
isDark
(
row
,
col
+
4
)
&&
!
qrCode
.
isDark
(
row
,
col
+
5
)
&&
qrCode
.
isDark
(
row
,
col
+
6
))
{
lostPoint
+=
40
;
}
}
}
for
(
var
col
=
0
;
col
<
moduleCount
;
col
++
)
{
for
(
var
row
=
0
;
row
<
moduleCount
-
6
;
row
++
)
{
if
(
qrCode
.
isDark
(
row
,
col
)
&&
!
qrCode
.
isDark
(
row
+
1
,
col
)
&&
qrCode
.
isDark
(
row
+
2
,
col
)
&&
qrCode
.
isDark
(
row
+
3
,
col
)
&&
qrCode
.
isDark
(
row
+
4
,
col
)
&&
!
qrCode
.
isDark
(
row
+
5
,
col
)
&&
qrCode
.
isDark
(
row
+
6
,
col
))
{
lostPoint
+=
40
;
}
}
}
var
darkCount
=
0
;
for
(
var
col
=
0
;
col
<
moduleCount
;
col
++
)
{
for
(
var
row
=
0
;
row
<
moduleCount
;
row
++
)
{
if
(
qrCode
.
isDark
(
row
,
col
))
{
darkCount
++
;
}
}
}
var
ratio
=
Math
.
abs
(
100
*
darkCount
/
moduleCount
/
moduleCount
-
50
)
/
5
;
lostPoint
+=
ratio
*
10
;
return
lostPoint
;
}
};
var
QRMath
=
{
glog
:
function
(
n
)
{
if
(
n
<
1
)
{
throw
new
Error
(
"glog("
+
n
+
")"
);
}
return
QRMath
.
LOG_TABLE
[
n
];
},
gexp
:
function
(
n
)
{
while
(
n
<
0
)
{
n
+=
255
;
}
while
(
n
>=
256
)
{
n
-=
255
;
}
return
QRMath
.
EXP_TABLE
[
n
];
},
EXP_TABLE
:
new
Array
(
256
),
LOG_TABLE
:
new
Array
(
256
)
};
for
(
var
i
=
0
;
i
<
8
;
i
++
)
{
QRMath
.
EXP_TABLE
[
i
]
=
1
<<
i
;
}
for
(
var
i
=
8
;
i
<
256
;
i
++
)
{
QRMath
.
EXP_TABLE
[
i
]
=
QRMath
.
EXP_TABLE
[
i
-
4
]
^
QRMath
.
EXP_TABLE
[
i
-
5
]
^
QRMath
.
EXP_TABLE
[
i
-
6
]
^
QRMath
.
EXP_TABLE
[
i
-
8
];
}
for
(
var
i
=
0
;
i
<
255
;
i
++
)
{
QRMath
.
LOG_TABLE
[
QRMath
.
EXP_TABLE
[
i
]]
=
i
;
}
function
QRPolynomial
(
num
,
shift
)
{
if
(
num
.
length
==
undefined
)
{
throw
new
Error
(
num
.
length
+
"/"
+
shift
);
}
var
offset
=
0
;
while
(
offset
<
num
.
length
&&
num
[
offset
]
==
0
)
{
offset
++
;
}
this
.
num
=
new
Array
(
num
.
length
-
offset
+
shift
);
for
(
var
i
=
0
;
i
<
num
.
length
-
offset
;
i
++
)
{
this
.
num
[
i
]
=
num
[
i
+
offset
];
}
}
QRPolynomial
.
prototype
=
{
get
:
function
(
index
)
{
return
this
.
num
[
index
];
},
getLength
:
function
()
{
return
this
.
num
.
length
;
},
multiply
:
function
(
e
)
{
var
num
=
new
Array
(
this
.
getLength
()
+
e
.
getLength
()
-
1
);
for
(
var
i
=
0
;
i
<
this
.
getLength
();
i
++
)
{
for
(
var
j
=
0
;
j
<
e
.
getLength
();
j
++
)
{
num
[
i
+
j
]
^=
QRMath
.
gexp
(
QRMath
.
glog
(
this
.
get
(
i
))
+
QRMath
.
glog
(
e
.
get
(
j
)));
}
}
return
new
QRPolynomial
(
num
,
0
);
},
mod
:
function
(
e
)
{
if
(
this
.
getLength
()
-
e
.
getLength
()
<
0
)
{
return
this
;
}
var
ratio
=
QRMath
.
glog
(
this
.
get
(
0
))
-
QRMath
.
glog
(
e
.
get
(
0
));
var
num
=
new
Array
(
this
.
getLength
());
for
(
var
i
=
0
;
i
<
this
.
getLength
();
i
++
)
{
num
[
i
]
=
this
.
get
(
i
);
}
for
(
var
i
=
0
;
i
<
e
.
getLength
();
i
++
)
{
num
[
i
]
^=
QRMath
.
gexp
(
QRMath
.
glog
(
e
.
get
(
i
))
+
ratio
);
}
return
new
QRPolynomial
(
num
,
0
).
mod
(
e
);
}
};
function
QRRSBlock
(
totalCount
,
dataCount
)
{
this
.
totalCount
=
totalCount
;
this
.
dataCount
=
dataCount
;
}
QRRSBlock
.
RS_BLOCK_TABLE
=
[[
1
,
26
,
19
],
[
1
,
26
,
16
],
[
1
,
26
,
13
],
[
1
,
26
,
9
],
[
1
,
44
,
34
],
[
1
,
44
,
28
],
[
1
,
44
,
22
],
[
1
,
44
,
16
],
[
1
,
70
,
55
],
[
1
,
70
,
44
],
[
2
,
35
,
17
],
[
2
,
35
,
13
],
[
1
,
100
,
80
],
[
2
,
50
,
32
],
[
2
,
50
,
24
],
[
4
,
25
,
9
],
[
1
,
134
,
108
],
[
2
,
67
,
43
],
[
2
,
33
,
15
,
2
,
34
,
16
],
[
2
,
33
,
11
,
2
,
34
,
12
],
[
2
,
86
,
68
],
[
4
,
43
,
27
],
[
4
,
43
,
19
],
[
4
,
43
,
15
],
[
2
,
98
,
78
],
[
4
,
49
,
31
],
[
2
,
32
,
14
,
4
,
33
,
15
],
[
4
,
39
,
13
,
1
,
40
,
14
],
[
2
,
121
,
97
],
[
2
,
60
,
38
,
2
,
61
,
39
],
[
4
,
40
,
18
,
2
,
41
,
19
],
[
4
,
40
,
14
,
2
,
41
,
15
],
[
2
,
146
,
116
],
[
3
,
58
,
36
,
2
,
59
,
37
],
[
4
,
36
,
16
,
4
,
37
,
17
],
[
4
,
36
,
12
,
4
,
37
,
13
],
[
2
,
86
,
68
,
2
,
87
,
69
],
[
4
,
69
,
43
,
1
,
70
,
44
],
[
6
,
43
,
19
,
2
,
44
,
20
],
[
6
,
43
,
15
,
2
,
44
,
16
],
[
4
,
101
,
81
],
[
1
,
80
,
50
,
4
,
81
,
51
],
[
4
,
50
,
22
,
4
,
51
,
23
],
[
3
,
36
,
12
,
8
,
37
,
13
],
[
2
,
116
,
92
,
2
,
117
,
93
],
[
6
,
58
,
36
,
2
,
59
,
37
],
[
4
,
46
,
20
,
6
,
47
,
21
],
[
7
,
42
,
14
,
4
,
43
,
15
],
[
4
,
133
,
107
],
[
8
,
59
,
37
,
1
,
60
,
38
],
[
8
,
44
,
20
,
4
,
45
,
21
],
[
12
,
33
,
11
,
4
,
34
,
12
],
[
3
,
145
,
115
,
1
,
146
,
116
],
[
4
,
64
,
40
,
5
,
65
,
41
],
[
11
,
36
,
16
,
5
,
37
,
17
],
[
11
,
36
,
12
,
5
,
37
,
13
],
[
5
,
109
,
87
,
1
,
110
,
88
],
[
5
,
65
,
41
,
5
,
66
,
42
],
[
5
,
54
,
24
,
7
,
55
,
25
],
[
11
,
36
,
12
],
[
5
,
122
,
98
,
1
,
123
,
99
],
[
7
,
73
,
45
,
3
,
74
,
46
],
[
15
,
43
,
19
,
2
,
44
,
20
],
[
3
,
45
,
15
,
13
,
46
,
16
],
[
1
,
135
,
107
,
5
,
136
,
108
],
[
10
,
74
,
46
,
1
,
75
,
47
],
[
1
,
50
,
22
,
15
,
51
,
23
],
[
2
,
42
,
14
,
17
,
43
,
15
],
[
5
,
150
,
120
,
1
,
151
,
121
],
[
9
,
69
,
43
,
4
,
70
,
44
],
[
17
,
50
,
22
,
1
,
51
,
23
],
[
2
,
42
,
14
,
19
,
43
,
15
],
[
3
,
141
,
113
,
4
,
142
,
114
],
[
3
,
70
,
44
,
11
,
71
,
45
],
[
17
,
47
,
21
,
4
,
48
,
22
],
[
9
,
39
,
13
,
16
,
40
,
14
],
[
3
,
135
,
107
,
5
,
136
,
108
],
[
3
,
67
,
41
,
13
,
68
,
42
],
[
15
,
54
,
24
,
5
,
55
,
25
],
[
15
,
43
,
15
,
10
,
44
,
16
],
[
4
,
144
,
116
,
4
,
145
,
117
],
[
17
,
68
,
42
],
[
17
,
50
,
22
,
6
,
51
,
23
],
[
19
,
46
,
16
,
6
,
47
,
17
],
[
2
,
139
,
111
,
7
,
140
,
112
],
[
17
,
74
,
46
],
[
7
,
54
,
24
,
16
,
55
,
25
],
[
34
,
37
,
13
],
[
4
,
151
,
121
,
5
,
152
,
122
],
[
4
,
75
,
47
,
14
,
76
,
48
],
[
11
,
54
,
24
,
14
,
55
,
25
],
[
16
,
45
,
15
,
14
,
46
,
16
],
[
6
,
147
,
117
,
4
,
148
,
118
],
[
6
,
73
,
45
,
14
,
74
,
46
],
[
11
,
54
,
24
,
16
,
55
,
25
],
[
30
,
46
,
16
,
2
,
47
,
17
],
[
8
,
132
,
106
,
4
,
133
,
107
],
[
8
,
75
,
47
,
13
,
76
,
48
],
[
7
,
54
,
24
,
22
,
55
,
25
],
[
22
,
45
,
15
,
13
,
46
,
16
],
[
10
,
142
,
114
,
2
,
143
,
115
],
[
19
,
74
,
46
,
4
,
75
,
47
],
[
28
,
50
,
22
,
6
,
51
,
23
],
[
33
,
46
,
16
,
4
,
47
,
17
],
[
8
,
152
,
122
,
4
,
153
,
123
],
[
22
,
73
,
45
,
3
,
74
,
46
],
[
8
,
53
,
23
,
26
,
54
,
24
],
[
12
,
45
,
15
,
28
,
46
,
16
],
[
3
,
147
,
117
,
10
,
148
,
118
],
[
3
,
73
,
45
,
23
,
74
,
46
],
[
4
,
54
,
24
,
31
,
55
,
25
],
[
11
,
45
,
15
,
31
,
46
,
16
],
[
7
,
146
,
116
,
7
,
147
,
117
],
[
21
,
73
,
45
,
7
,
74
,
46
],
[
1
,
53
,
23
,
37
,
54
,
24
],
[
19
,
45
,
15
,
26
,
46
,
16
],
[
5
,
145
,
115
,
10
,
146
,
116
],
[
19
,
75
,
47
,
10
,
76
,
48
],
[
15
,
54
,
24
,
25
,
55
,
25
],
[
23
,
45
,
15
,
25
,
46
,
16
],
[
13
,
145
,
115
,
3
,
146
,
116
],
[
2
,
74
,
46
,
29
,
75
,
47
],
[
42
,
54
,
24
,
1
,
55
,
25
],
[
23
,
45
,
15
,
28
,
46
,
16
],
[
17
,
145
,
115
],
[
10
,
74
,
46
,
23
,
75
,
47
],
[
10
,
54
,
24
,
35
,
55
,
25
],
[
19
,
45
,
15
,
35
,
46
,
16
],
[
17
,
145
,
115
,
1
,
146
,
116
],
[
14
,
74
,
46
,
21
,
75
,
47
],
[
29
,
54
,
24
,
19
,
55
,
25
],
[
11
,
45
,
15
,
46
,
46
,
16
],
[
13
,
145
,
115
,
6
,
146
,
116
],
[
14
,
74
,
46
,
23
,
75
,
47
],
[
44
,
54
,
24
,
7
,
55
,
25
],
[
59
,
46
,
16
,
1
,
47
,
17
],
[
12
,
151
,
121
,
7
,
152
,
122
],
[
12
,
75
,
47
,
26
,
76
,
48
],
[
39
,
54
,
24
,
14
,
55
,
25
],
[
22
,
45
,
15
,
41
,
46
,
16
],
[
6
,
151
,
121
,
14
,
152
,
122
],
[
6
,
75
,
47
,
34
,
76
,
48
],
[
46
,
54
,
24
,
10
,
55
,
25
],
[
2
,
45
,
15
,
64
,
46
,
16
],
[
17
,
152
,
122
,
4
,
153
,
123
],
[
29
,
74
,
46
,
14
,
75
,
47
],
[
49
,
54
,
24
,
10
,
55
,
25
],
[
24
,
45
,
15
,
46
,
46
,
16
],
[
4
,
152
,
122
,
18
,
153
,
123
],
[
13
,
74
,
46
,
32
,
75
,
47
],
[
48
,
54
,
24
,
14
,
55
,
25
],
[
42
,
45
,
15
,
32
,
46
,
16
],
[
20
,
147
,
117
,
4
,
148
,
118
],
[
40
,
75
,
47
,
7
,
76
,
48
],
[
43
,
54
,
24
,
22
,
55
,
25
],
[
10
,
45
,
15
,
67
,
46
,
16
],
[
19
,
148
,
118
,
6
,
149
,
119
],
[
18
,
75
,
47
,
31
,
76
,
48
],
[
34
,
54
,
24
,
34
,
55
,
25
],
[
20
,
45
,
15
,
61
,
46
,
16
]];
QRRSBlock
.
getRSBlocks
=
function
(
typeNumber
,
errorCorrectLevel
)
{
var
rsBlock
=
QRRSBlock
.
getRsBlockTable
(
typeNumber
,
errorCorrectLevel
);
if
(
rsBlock
==
undefined
)
{
throw
new
Error
(
"bad rs block @ typeNumber:"
+
typeNumber
+
"/errorCorrectLevel:"
+
errorCorrectLevel
);
}
var
length
=
rsBlock
.
length
/
3
;
var
list
=
[];
for
(
var
i
=
0
;
i
<
length
;
i
++
)
{
var
count
=
rsBlock
[
i
*
3
+
0
];
var
totalCount
=
rsBlock
[
i
*
3
+
1
];
var
dataCount
=
rsBlock
[
i
*
3
+
2
];
for
(
var
j
=
0
;
j
<
count
;
j
++
)
{
list
.
push
(
new
QRRSBlock
(
totalCount
,
dataCount
));
}
}
return
list
;
};
QRRSBlock
.
getRsBlockTable
=
function
(
typeNumber
,
errorCorrectLevel
)
{
switch
(
errorCorrectLevel
)
{
case
QRErrorCorrectLevel
.
L
:
return
QRRSBlock
.
RS_BLOCK_TABLE
[(
typeNumber
-
1
)
*
4
+
0
];
case
QRErrorCorrectLevel
.
M
:
return
QRRSBlock
.
RS_BLOCK_TABLE
[(
typeNumber
-
1
)
*
4
+
1
];
case
QRErrorCorrectLevel
.
Q
:
return
QRRSBlock
.
RS_BLOCK_TABLE
[(
typeNumber
-
1
)
*
4
+
2
];
case
QRErrorCorrectLevel
.
H
:
return
QRRSBlock
.
RS_BLOCK_TABLE
[(
typeNumber
-
1
)
*
4
+
3
];
default
:
return
undefined
;
}
};
function
QRBitBuffer
()
{
this
.
buffer
=
[];
this
.
length
=
0
;
}
QRBitBuffer
.
prototype
=
{
get
:
function
(
index
)
{
var
bufIndex
=
Math
.
floor
(
index
/
8
);
return
((
this
.
buffer
[
bufIndex
]
>>>
(
7
-
index
%
8
))
&
1
)
==
1
;
},
put
:
function
(
num
,
length
)
{
for
(
var
i
=
0
;
i
<
length
;
i
++
)
{
this
.
putBit
(((
num
>>>
(
length
-
i
-
1
))
&
1
)
==
1
);
}
},
getLengthInBits
:
function
()
{
return
this
.
length
;
},
putBit
:
function
(
bit
)
{
var
bufIndex
=
Math
.
floor
(
this
.
length
/
8
);
if
(
this
.
buffer
.
length
<=
bufIndex
)
{
this
.
buffer
.
push
(
0
);
}
if
(
bit
)
{
this
.
buffer
[
bufIndex
]
|=
(
0x80
>>>
(
this
.
length
%
8
));
}
this
.
length
++
;
}
};
var
QRCodeLimitLength
=
[[
17
,
14
,
11
,
7
],
[
32
,
26
,
20
,
14
],
[
53
,
42
,
32
,
24
],
[
78
,
62
,
46
,
34
],
[
106
,
84
,
60
,
44
],
[
134
,
106
,
74
,
58
],
[
154
,
122
,
86
,
64
],
[
192
,
152
,
108
,
84
],
[
230
,
180
,
130
,
98
],
[
271
,
213
,
151
,
119
],
[
321
,
251
,
177
,
137
],
[
367
,
287
,
203
,
155
],
[
425
,
331
,
241
,
177
],
[
458
,
362
,
258
,
194
],
[
520
,
412
,
292
,
220
],
[
586
,
450
,
322
,
250
],
[
644
,
504
,
364
,
280
],
[
718
,
560
,
394
,
310
],
[
792
,
624
,
442
,
338
],
[
858
,
666
,
482
,
382
],
[
929
,
711
,
509
,
403
],
[
1003
,
779
,
565
,
439
],
[
1091
,
857
,
611
,
461
],
[
1171
,
911
,
661
,
511
],
[
1273
,
997
,
715
,
535
],
[
1367
,
1059
,
751
,
593
],
[
1465
,
1125
,
805
,
625
],
[
1528
,
1190
,
868
,
658
],
[
1628
,
1264
,
908
,
698
],
[
1732
,
1370
,
982
,
742
],
[
1840
,
1452
,
1030
,
790
],
[
1952
,
1538
,
1112
,
842
],
[
2068
,
1628
,
1168
,
898
],
[
2188
,
1722
,
1228
,
958
],
[
2303
,
1809
,
1283
,
983
],
[
2431
,
1911
,
1351
,
1051
],
[
2563
,
1989
,
1423
,
1093
],
[
2699
,
2099
,
1499
,
1139
],
[
2809
,
2213
,
1579
,
1219
],
[
2953
,
2331
,
1663
,
1273
]];
function
_isSupportCanvas
()
{
return
typeof
CanvasRenderingContext2D
!=
"undefined"
;
}
// android 2.x doesn't support Data-URI spec
function
_getAndroid
()
{
var
android
=
false
;
var
sAgent
=
navigator
.
userAgent
;
if
(
/android/i
.
test
(
sAgent
))
{
// android
android
=
true
;
var
aMat
=
sAgent
.
toString
().
match
(
/android
([
0-9
]\.[
0-9
])
/i
);
if
(
aMat
&&
aMat
[
1
])
{
android
=
parseFloat
(
aMat
[
1
]);
}
}
return
android
;
}
var
svgDrawer
=
(
function
()
{
var
Drawing
=
function
(
el
,
htOption
)
{
this
.
_el
=
el
;
this
.
_htOption
=
htOption
;
};
Drawing
.
prototype
.
draw
=
function
(
oQRCode
)
{
var
_htOption
=
this
.
_htOption
;
var
_el
=
this
.
_el
;
var
nCount
=
oQRCode
.
getModuleCount
();
var
nWidth
=
Math
.
floor
(
_htOption
.
width
/
nCount
);
var
nHeight
=
Math
.
floor
(
_htOption
.
height
/
nCount
);
this
.
clear
();
function
makeSVG
(
tag
,
attrs
)
{
var
el
=
document
.
createElementNS
(
'http://www.w3.org/2000/svg'
,
tag
);
for
(
var
k
in
attrs
)
if
(
attrs
.
hasOwnProperty
(
k
))
el
.
setAttribute
(
k
,
attrs
[
k
]);
return
el
;
}
var
svg
=
makeSVG
(
"svg"
,
{
'viewBox'
:
'0 0 '
+
String
(
nCount
)
+
" "
+
String
(
nCount
),
'width'
:
'100%'
,
'height'
:
'100%'
,
'fill'
:
_htOption
.
colorLight
});
svg
.
setAttributeNS
(
"http://www.w3.org/2000/xmlns/"
,
"xmlns:xlink"
,
"http://www.w3.org/1999/xlink"
);
_el
.
appendChild
(
svg
);
svg
.
appendChild
(
makeSVG
(
"rect"
,
{
"fill"
:
_htOption
.
colorLight
,
"width"
:
"100%"
,
"height"
:
"100%"
}));
svg
.
appendChild
(
makeSVG
(
"rect"
,
{
"fill"
:
_htOption
.
colorDark
,
"width"
:
"1"
,
"height"
:
"1"
,
"id"
:
"template"
}));
for
(
var
row
=
0
;
row
<
nCount
;
row
++
)
{
for
(
var
col
=
0
;
col
<
nCount
;
col
++
)
{
if
(
oQRCode
.
isDark
(
row
,
col
))
{
var
child
=
makeSVG
(
"use"
,
{
"x"
:
String
(
col
),
"y"
:
String
(
row
)});
child
.
setAttributeNS
(
"http://www.w3.org/1999/xlink"
,
"href"
,
"#template"
)
svg
.
appendChild
(
child
);
}
}
}
};
Drawing
.
prototype
.
clear
=
function
()
{
while
(
this
.
_el
.
hasChildNodes
())
this
.
_el
.
removeChild
(
this
.
_el
.
lastChild
);
};
return
Drawing
;
})();
var
useSVG
=
document
.
documentElement
.
tagName
.
toLowerCase
()
===
"svg"
;
// Drawing in DOM by using Table tag
var
Drawing
=
useSVG
?
svgDrawer
:
!
_isSupportCanvas
()
?
(
function
()
{
var
Drawing
=
function
(
el
,
htOption
)
{
this
.
_el
=
el
;
this
.
_htOption
=
htOption
;
};
/**
* Draw the QRCode
*
* @param {QRCode} oQRCode
*/
Drawing
.
prototype
.
draw
=
function
(
oQRCode
)
{
var
_htOption
=
this
.
_htOption
;
var
_el
=
this
.
_el
;
var
nCount
=
oQRCode
.
getModuleCount
();
var
nWidth
=
Math
.
floor
(
_htOption
.
width
/
nCount
);
var
nHeight
=
Math
.
floor
(
_htOption
.
height
/
nCount
);
var
aHTML
=
[
'<table style="border:0;border-collapse:collapse;">'
];
for
(
var
row
=
0
;
row
<
nCount
;
row
++
)
{
aHTML
.
push
(
'<tr>'
);
for
(
var
col
=
0
;
col
<
nCount
;
col
++
)
{
aHTML
.
push
(
'<td style="border:0;border-collapse:collapse;padding:0;margin:0;width:'
+
nWidth
+
'px;height:'
+
nHeight
+
'px;background-color:'
+
(
oQRCode
.
isDark
(
row
,
col
)
?
_htOption
.
colorDark
:
_htOption
.
colorLight
)
+
';"></td>'
);
}
aHTML
.
push
(
'</tr>'
);
}
aHTML
.
push
(
'</table>'
);
_el
.
innerHTML
=
aHTML
.
join
(
''
);
// Fix the margin values as real size.
var
elTable
=
_el
.
childNodes
[
0
];
var
nLeftMarginTable
=
(
_htOption
.
width
-
elTable
.
offsetWidth
)
/
2
;
var
nTopMarginTable
=
(
_htOption
.
height
-
elTable
.
offsetHeight
)
/
2
;
if
(
nLeftMarginTable
>
0
&&
nTopMarginTable
>
0
)
{
elTable
.
style
.
margin
=
nTopMarginTable
+
"px "
+
nLeftMarginTable
+
"px"
;
}
};
/**
* Clear the QRCode
*/
Drawing
.
prototype
.
clear
=
function
()
{
this
.
_el
.
innerHTML
=
''
;
};
return
Drawing
;
})()
:
(
function
()
{
// Drawing in Canvas
function
_onMakeImage
()
{
this
.
_elImage
.
src
=
this
.
_elCanvas
.
toDataURL
(
"image/png"
);
this
.
_elImage
.
style
.
display
=
"block"
;
this
.
_elCanvas
.
style
.
display
=
"none"
;
}
// Android 2.1 bug workaround
// http://code.google.com/p/android/issues/detail?id=5141
if
(
this
.
_android
&&
this
.
_android
<=
2.1
)
{
var
factor
=
1
/
window
.
devicePixelRatio
;
var
drawImage
=
CanvasRenderingContext2D
.
prototype
.
drawImage
;
CanvasRenderingContext2D
.
prototype
.
drawImage
=
function
(
image
,
sx
,
sy
,
sw
,
sh
,
dx
,
dy
,
dw
,
dh
)
{
if
((
"nodeName"
in
image
)
&&
/img/i
.
test
(
image
.
nodeName
))
{
for
(
var
i
=
arguments
.
length
-
1
;
i
>=
1
;
i
--
)
{
arguments
[
i
]
=
arguments
[
i
]
*
factor
;
}
}
else
if
(
typeof
dw
==
"undefined"
)
{
arguments
[
1
]
*=
factor
;
arguments
[
2
]
*=
factor
;
arguments
[
3
]
*=
factor
;
arguments
[
4
]
*=
factor
;
}
drawImage
.
apply
(
this
,
arguments
);
};
}
/**
* Check whether the user's browser supports Data URI or not
*
* @private
* @param {Function} fSuccess Occurs if it supports Data URI
* @param {Function} fFail Occurs if it doesn't support Data URI
*/
function
_safeSetDataURI
(
fSuccess
,
fFail
)
{
var
self
=
this
;
self
.
_fFail
=
fFail
;
self
.
_fSuccess
=
fSuccess
;
// Check it just once
if
(
self
.
_bSupportDataURI
===
null
)
{
var
el
=
document
.
createElement
(
"img"
);
var
fOnError
=
function
()
{
self
.
_bSupportDataURI
=
false
;
if
(
self
.
_fFail
)
{
self
.
_fFail
.
call
(
self
);
}
};
var
fOnSuccess
=
function
()
{
self
.
_bSupportDataURI
=
true
;
if
(
self
.
_fSuccess
)
{
self
.
_fSuccess
.
call
(
self
);
}
};
el
.
onabort
=
fOnError
;
el
.
onerror
=
fOnError
;
el
.
onload
=
fOnSuccess
;
el
.
src
=
"data:image/gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
;
// the Image contains 1px data.
return
;
}
else
if
(
self
.
_bSupportDataURI
===
true
&&
self
.
_fSuccess
)
{
self
.
_fSuccess
.
call
(
self
);
}
else
if
(
self
.
_bSupportDataURI
===
false
&&
self
.
_fFail
)
{
self
.
_fFail
.
call
(
self
);
}
};
/**
* Drawing QRCode by using canvas
*
* @constructor
* @param {HTMLElement} el
* @param {Object} htOption QRCode Options
*/
var
Drawing
=
function
(
el
,
htOption
)
{
this
.
_bIsPainted
=
false
;
this
.
_android
=
_getAndroid
();
this
.
_htOption
=
htOption
;
this
.
_elCanvas
=
document
.
createElement
(
"canvas"
);
this
.
_elCanvas
.
width
=
htOption
.
width
;
this
.
_elCanvas
.
height
=
htOption
.
height
;
el
.
appendChild
(
this
.
_elCanvas
);
this
.
_el
=
el
;
this
.
_oContext
=
this
.
_elCanvas
.
getContext
(
"2d"
);
this
.
_bIsPainted
=
false
;
this
.
_elImage
=
document
.
createElement
(
"img"
);
this
.
_elImage
.
alt
=
"Scan me!"
;
this
.
_elImage
.
style
.
display
=
"none"
;
this
.
_el
.
appendChild
(
this
.
_elImage
);
this
.
_bSupportDataURI
=
null
;
};
/**
* Draw the QRCode
*
* @param {QRCode} oQRCode
*/
Drawing
.
prototype
.
draw
=
function
(
oQRCode
)
{
var
_elImage
=
this
.
_elImage
;
var
_oContext
=
this
.
_oContext
;
var
_htOption
=
this
.
_htOption
;
var
nCount
=
oQRCode
.
getModuleCount
();
var
nWidth
=
_htOption
.
width
/
nCount
;
var
nHeight
=
_htOption
.
height
/
nCount
;
var
nRoundedWidth
=
Math
.
round
(
nWidth
);
var
nRoundedHeight
=
Math
.
round
(
nHeight
);
_elImage
.
style
.
display
=
"none"
;
this
.
clear
();
for
(
var
row
=
0
;
row
<
nCount
;
row
++
)
{
for
(
var
col
=
0
;
col
<
nCount
;
col
++
)
{
var
bIsDark
=
oQRCode
.
isDark
(
row
,
col
);
var
nLeft
=
col
*
nWidth
;
var
nTop
=
row
*
nHeight
;
_oContext
.
strokeStyle
=
bIsDark
?
_htOption
.
colorDark
:
_htOption
.
colorLight
;
_oContext
.
lineWidth
=
1
;
_oContext
.
fillStyle
=
bIsDark
?
_htOption
.
colorDark
:
_htOption
.
colorLight
;
_oContext
.
fillRect
(
nLeft
,
nTop
,
nWidth
,
nHeight
);
// 안티 앨리어싱 방지 처리
_oContext
.
strokeRect
(
Math
.
floor
(
nLeft
)
+
0.5
,
Math
.
floor
(
nTop
)
+
0.5
,
nRoundedWidth
,
nRoundedHeight
);
_oContext
.
strokeRect
(
Math
.
ceil
(
nLeft
)
-
0.5
,
Math
.
ceil
(
nTop
)
-
0.5
,
nRoundedWidth
,
nRoundedHeight
);
}
}
this
.
_bIsPainted
=
true
;
};
/**
* Make the image from Canvas if the browser supports Data URI.
*/
Drawing
.
prototype
.
makeImage
=
function
()
{
if
(
this
.
_bIsPainted
)
{
_safeSetDataURI
.
call
(
this
,
_onMakeImage
);
}
};
/**
* Return whether the QRCode is painted or not
*
* @return {Boolean}
*/
Drawing
.
prototype
.
isPainted
=
function
()
{
return
this
.
_bIsPainted
;
};
/**
* Clear the QRCode
*/
Drawing
.
prototype
.
clear
=
function
()
{
this
.
_oContext
.
clearRect
(
0
,
0
,
this
.
_elCanvas
.
width
,
this
.
_elCanvas
.
height
);
this
.
_bIsPainted
=
false
;
};
/**
* @private
* @param {Number} nNumber
*/
Drawing
.
prototype
.
round
=
function
(
nNumber
)
{
if
(
!
nNumber
)
{
return
nNumber
;
}
return
Math
.
floor
(
nNumber
*
1000
)
/
1000
;
};
return
Drawing
;
})();
/**
* Get the type by string length
*
* @private
* @param {String} sText
* @param {Number} nCorrectLevel
* @return {Number} type
*/
function
_getTypeNumber
(
sText
,
nCorrectLevel
)
{
var
nType
=
1
;
var
length
=
_getUTF8Length
(
sText
);
for
(
var
i
=
0
,
len
=
QRCodeLimitLength
.
length
;
i
<=
len
;
i
++
)
{
var
nLimit
=
0
;
switch
(
nCorrectLevel
)
{
case
QRErrorCorrectLevel
.
L
:
nLimit
=
QRCodeLimitLength
[
i
][
0
];
break
;
case
QRErrorCorrectLevel
.
M
:
nLimit
=
QRCodeLimitLength
[
i
][
1
];
break
;
case
QRErrorCorrectLevel
.
Q
:
nLimit
=
QRCodeLimitLength
[
i
][
2
];
break
;
case
QRErrorCorrectLevel
.
H
:
nLimit
=
QRCodeLimitLength
[
i
][
3
];
break
;
}
if
(
length
<=
nLimit
)
{
break
;
}
else
{
nType
++
;
}
}
if
(
nType
>
QRCodeLimitLength
.
length
)
{
throw
new
Error
(
"Too long data"
);
}
return
nType
;
}
function
_getUTF8Length
(
sText
)
{
var
replacedText
=
encodeURI
(
sText
).
toString
().
replace
(
/
\%[
0-9a-fA-F
]{2}
/g
,
'a'
);
return
replacedText
.
length
+
(
replacedText
.
length
!=
sText
?
3
:
0
);
}
/**
* @class QRCode
* @constructor
* @example
* new QRCode(document.getElementById("test"), "http://jindo.dev.naver.com/collie");
*
* @example
* var oQRCode = new QRCode("test", {
* text : "http://naver.com",
* width : 128,
* height : 128
* });
*
* oQRCode.clear(); // Clear the QRCode.
* oQRCode.makeCode("http://map.naver.com"); // Re-create the QRCode.
*
* @param {HTMLElement|String} el target element or 'id' attribute of element.
* @param {Object|String} vOption
* @param {String} vOption.text QRCode link data
* @param {Number} [vOption.width=256]
* @param {Number} [vOption.height=256]
* @param {String} [vOption.colorDark="#000000"]
* @param {String} [vOption.colorLight="#ffffff"]
* @param {QRCode.CorrectLevel} [vOption.correctLevel=QRCode.CorrectLevel.H] [L|M|Q|H]
*/
QRCode
=
function
(
el
,
vOption
)
{
this
.
_htOption
=
{
width
:
256
,
height
:
256
,
typeNumber
:
4
,
colorDark
:
"#000000"
,
colorLight
:
"#ffffff"
,
correctLevel
:
QRErrorCorrectLevel
.
H
};
if
(
typeof
vOption
===
'string'
)
{
vOption
=
{
text
:
vOption
};
}
// Overwrites options
if
(
vOption
)
{
for
(
var
i
in
vOption
)
{
this
.
_htOption
[
i
]
=
vOption
[
i
];
}
}
if
(
typeof
el
==
"string"
)
{
el
=
document
.
getElementById
(
el
);
}
if
(
this
.
_htOption
.
useSVG
)
{
Drawing
=
svgDrawer
;
}
this
.
_android
=
_getAndroid
();
this
.
_el
=
el
;
this
.
_oQRCode
=
null
;
this
.
_oDrawing
=
new
Drawing
(
this
.
_el
,
this
.
_htOption
);
if
(
this
.
_htOption
.
text
)
{
this
.
makeCode
(
this
.
_htOption
.
text
);
}
};
/**
* Make the QRCode
*
* @param {String} sText link data
*/
QRCode
.
prototype
.
makeCode
=
function
(
sText
)
{
this
.
_oQRCode
=
new
QRCodeModel
(
_getTypeNumber
(
sText
,
this
.
_htOption
.
correctLevel
),
this
.
_htOption
.
correctLevel
);
this
.
_oQRCode
.
addData
(
sText
);
this
.
_oQRCode
.
make
();
this
.
_el
.
title
=
sText
;
this
.
_oDrawing
.
draw
(
this
.
_oQRCode
);
this
.
makeImage
();
return
this
;
};
/**
* Make the Image from Canvas element
* - It occurs automatically
* - Android below 3 doesn't support Data-URI spec.
*
* @private
*/
QRCode
.
prototype
.
makeImage
=
function
()
{
if
(
typeof
this
.
_oDrawing
.
makeImage
==
"function"
&&
(
!
this
.
_android
||
this
.
_android
>=
3
))
{
this
.
_oDrawing
.
makeImage
();
}
return
this
;
};
/**
* Clear the QRCode
*/
QRCode
.
prototype
.
clear
=
function
()
{
this
.
_oDrawing
.
clear
();
return
this
;
};
/**
* @name QRCode.CorrectLevel
*/
QRCode
.
CorrectLevel
=
QRErrorCorrectLevel
;
return
QRCode
;
})();
...
...
public/scss/passport/_login.css
View file @
5aad2c6
...
...
@@ -255,7 +255,7 @@
.scan
{
display
:
block
;
width
:
30px
;
height
:
30
px
;
height
:
29
px
;
background
:
url(/passport/scan.png)
no-repeat
;
float
:
left
;
margin-right
:
15px
;
...
...
Please
register
or
login
to post a comment