I need to create a pattern password with a design for a mobile maintenance site so that when a customer opens a work order and if his cell phone has a screen lock it can be saved and if the technician needs to use it.
After much searching for what I find most promising is the PatternLock plugin . How do I pass the blocking drawing to another page, and after writing to the database, can I retrieve the information by leaving it drawn?
Here is an example:
index.html
script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script><linkhref="http://ignitersworld.com/lab/assets/css/patternLock.css?33" rel="stylesheet" type="text/css">
<title>Documento sem título</title>
</head>
<body>
<form>
<div id="patternHolder7" class="pattern-holder patt-holder" style="width: 310px; height: 310px;"></div>
<input type="submit"/>
</form>
<script src="http://ignitersworld.com/lab/assets/js/patternLockScript.js?33"></scrip</body></html>**patternLockScript.js**/*patternLock.jsv1.0.1Author:SudhanshuYadavCopyright(c)2015,2016SudhanshuYadav-ignitersworld.com,releasedundertheMITlicense.Demoon:ignitersworld.com/lab/patternLock.html*/;(function(factory){/**supportUMD***/varglobal=Function('returnthis')()||(42,eval)('this');if(typeofdefine==="function" && define.amd) {
define(["jquery"], function($) {
return (global.PatternLock = factory($, global));
});
} else if (typeof module === "object" && module.exports) {
module.exports = global.document ?
factory(require("jquery"), global) :
function(w) {
if (!w.document) {
throw new Error("patternLock requires a window with a document");
}
return factory(require("jquery")(w), w);
};
} else {
global.PatternLock = factory(global.jQuery, global);
}
}(function($, window, undefined) {
"use strict";
var document = window.document;
var nullFunc = function() {},
objectHolder = {};
//internal functions
function readyDom(iObj) {
var holder = iObj.holder,
option = iObj.option,
matrix = option.matrix,
margin = option.margin,
radius = option.radius,
html = ['<ul class="patt-wrap" style="padding:' + margin + 'px">'];
for (var i = 0, ln = matrix[0] * matrix[1]; i < ln; i++) {
html.push('<li class="patt-circ" style="margin:' + margin + 'px; width : ' + (radius * 2) + 'px; height : ' + (radius * 2) + 'px; -webkit-border-radius: ' + radius + 'px; -moz-border-radius: ' + radius + 'px; border-radius: ' + radius + 'px; "><div class="patt-dots"></div></li>');
}
html.push('</ul>');
holder.html(html.join('')).css({
'width': (matrix[1] * (radius * 2 + margin * 2) + margin * 2) + 'px',
'height': (matrix[0] * (radius * 2 + margin * 2) + margin * 2) + 'px'
});
//select pattern circle
iObj.pattCircle = iObj.holder.find('.patt-circ');
}
//return height and angle for lines
function getLengthAngle(x1, x2, y1, y2) {
var xDiff = x2 - x1,
yDiff = y2 - y1;
return {
length: Math.ceil(Math.sqrt(xDiff * xDiff + yDiff * yDiff)),
angle: Math.round((Math.atan2(yDiff, xDiff) * 180) / Math.PI)
};
}
var startHandler = function(e, obj) {
e.preventDefault();
var iObj = objectHolder[obj.token];
if (iObj.disabled) return;
//check if pattern is visible or not
if (!iObj.option.patternVisible) {
iObj.holder.addClass('patt-hidden');
}
var touchMove = e.type == "touchstart" ? "touchmove" : "mousemove",
touchEnd = e.type == "touchstart" ? "touchend" : "mouseup";
//assign events
$(this).on(touchMove + '.pattern-move', function(e) {
moveHandler.call(this, e, obj);
});
$(document).one(touchEnd, function() {
endHandler.call(this, e, obj);
});
//set pattern offset
var wrap = iObj.holder.find('.patt-wrap'),
offset = wrap[0].getBoundingClientRect();
iObj.wrapTop = offset.top;
iObj.wrapLeft = offset.left;
//reset pattern
obj.reset();
},
moveHandler = function(e, obj) {
e.preventDefault();
var x = e.clientX || e.originalEvent.touches[0].clientX,
y = e.clientY || e.originalEvent.touches[0].clientY,
iObj = objectHolder[obj.token],
option = iObj.option,
li = iObj.pattCircle,
patternAry = iObj.patternAry,
posObj = iObj.getIdxFromPoint(x, y),
idx = posObj.idx,
pattId = iObj.mapperFunc(idx) || idx;
if (patternAry.length > 0) {
var laMove = getLengthAngle(iObj.lineX1, posObj.x, iObj.lineY1, posObj.y);
iObj.line.css({
'width': (laMove.length + 10) + 'px',
'transform': 'rotate(' + laMove.angle + 'deg)'
});
}
if (idx && ((option.allowRepeat && patternAry[patternAry.length - 1] !== pattId) || patternAry.indexOf(pattId) === -1)) {
var elm = $(li[idx - 1]);
//mark if any points are in middle of previous point and current point, if it does check them
if (iObj.lastPosObj) {
var lastPosObj = iObj.lastPosObj,
ip = lastPosObj.i,
jp = lastPosObj.j,
xDelta = posObj.i - lastPosObj.i > 0 ? 1 : -1,
yDelta = posObj.j - lastPosObj.j > 0 ? 1 : -1,
iDiff = Math.abs(posObj.i - ip),
jDiff = Math.abs(posObj.j - jp);
while (((iDiff === 0 && jDiff > 1) || (jDiff === 0 && iDiff > 1) || (jDiff == iDiff && jDiff > 1))) {
ip = iDiff ? ip + xDelta : ip;
jp = jDiff ? jp + yDelta : jp;
iDiff = Math.abs(posObj.i - ip);
jDiff = Math.abs(posObj.j - jp);
var nextIdx = (jp - 1) * option.matrix[1] + ip,
nextPattId = iObj.mapperFunc(nextIdx) || nextIdx;
if (option.allowRepeat || patternAry.indexOf(nextPattId) == -1) {
//add direction to previous point and line
iObj.addDirectionClass({i: ip, j: jp});
//mark a point added
iObj.markPoint($(li[nextPattId - 1]), nextPattId);
//add line between the points
iObj.addLine({i: ip,j: jp});
}
}
}
//add direction to last point and line
if (iObj.lastPosObj) iObj.addDirectionClass(posObj);
//mark the initial point added
iObj.markPoint(elm, pattId);
//add initial line
iObj.addLine(posObj);
iObj.lastPosObj = posObj;
}
},
endHandler = function(e, obj) {
e.preventDefault();
var iObj = objectHolder[obj.token],
option = iObj.option,
pattern = iObj.patternAry.join(option.delimiter);
//remove hidden pattern class and remove event
iObj.holder.off('.pattern-move').removeClass('patt-hidden');
if (!pattern) return;
option.onDraw(pattern);
//to remove last line
iObj.line.remove();
if (iObj.rightPattern) {
if (pattern == iObj.rightPattern) {
iObj.onSuccess();
} else {
iObj.onError();
obj.error();
}
}
};
function InternalMethods() {}
InternalMethods.prototype = {
constructor: InternalMethods,
getIdxFromPoint: function(x, y) {
var option = this.option,
matrix = option.matrix,
xi = x - this.wrapLeft,
yi = y - this.wrapTop,
idx = null,
margin = option.margin,
plotLn = option.radius * 2 + margin * 2,
qsntX = Math.ceil(xi / plotLn),
qsntY = Math.ceil(yi / plotLn),
remX = xi % plotLn,
remY = yi % plotLn;
if (qsntX <= matrix[1] && qsntY <= matrix[0] && remX > margin * 2 && remY > margin * 2) {
idx = (qsntY - 1) * matrix[1] + qsntX;
}
return {
idx: idx,
i: qsntX,
j: qsntY,
x: xi,
y: yi
};
},
markPoint: function(elm, pattId) {
//add the current element on pattern
elm.addClass('hovered');
//push pattern on array
this.patternAry.push(pattId);
this.lastElm = elm;
},
//method to add lines between two element
addLine: function(posObj) {
var _this = this,
patternAry = _this.patternAry,
option = _this.option;
//add start point for line
var lineOnMove = option.lineOnMove,
margin = option.margin,
radius = option.radius,
newX = (posObj.i - 1) * (2 * margin + 2 * radius) + 2 * margin + radius,
newY = (posObj.j - 1) * (2 * margin + 2 * radius) + 2 * margin + radius;
if (patternAry.length > 1) {
//to fix line
var lA = getLengthAngle(_this.lineX1, newX, _this.lineY1, newY);
_this.line.css({
'width': (lA.length + 10) + 'px',
'transform': 'rotate(' + lA.angle + 'deg)'
});
if (!lineOnMove) _this.line.show();
}
//to create new line
var line = $('<div class="patt-lines" style="top:' + (newY - 5) + 'px; left:' + (newX - 5) + 'px"></div>');
_this.line = line;
_this.lineX1 = newX;
_this.lineY1 = newY;
//add on dom
_this.holder.append(line);
if (!lineOnMove) _this.line.hide();
},
// add direction on point and line
addDirectionClass: function(curPos) {
var point = this.lastElm,
line = this.line,
lastPos = this.lastPosObj;
var direction = [];
curPos.j - lastPos.j > 0 ? direction.push('s') : curPos.j - lastPos.j < 0 ? direction.push('n') : 0;
curPos.i - lastPos.i > 0 ? direction.push('e') : curPos.i - lastPos.i < 0 ? direction.push('w') : 0;
direction = direction.join('-');
if (direction) {
point.add(line).addClass(direction + " dir");
}
}
};
function PatternLock(selector, option) {
var self = this,
token = self.token = Math.random(),
iObj = objectHolder[token] = new InternalMethods(),
holder = iObj.holder = $(selector);
//if holder is not present return
if (holder.length === 0) return;
iObj.object = self;
//optimizing options
option = option || {};
var defaultsFixes = {
onDraw: nullFunc
};
var matrix = option.matrix;
if (matrix && matrix[0] * matrix[1] > 9) defaultsFixes.delimiter = ",";
option = iObj.option = $.extend({}, PatternLock.defaults, defaultsFixes, option);
readyDom(iObj);
//add class on holder
holder.addClass('patt-holder');
//change offset property of holder if it does not have any property
if (holder.css('position') == "static") holder.css('position', 'relative');
//assign event
holder.on("touchstart mousedown", function(e) {
startHandler.call(this, e, self);
});
//adding a mapper function
var mapper = option.mapper;
if (typeof mapper == "object") {
iObj.mapperFunc = function(idx) {
return mapper[idx];
};
} else if (typeof mapper == "function") {
iObj.mapperFunc = mapper;
} else {
iObj.mapperFunc = nullFunc;
}
//to delete from option object
iObj.option.mapper = null;
}
PatternLock.prototype = {
constructor: PatternLock,
//method to set options after initializtion
option: function(key, val) {
var iObj = objectHolder[this.token],
option = iObj.option;
//for set methods
if (val === undefined) {
return option[key];
}
//for setter
else {
option[key] = val;
if (key == "margin" || key == "matrix" || key == "radius") {
readyDom(iObj);
}
}
},
//get drawn pattern as string
getPattern: function() {
var iObj = objectHolder[this.token];
return (iObj.patternAry || []).join(iObj.option.delimiter);
},
//method to draw a pattern dynamically
//método para desenhar um padrão dinamicamente
setPattern: function(pattern) {
var iObj = objectHolder[this.token],
option = iObj.option,
matrix = option.matrix,
margin = option.margin,
radius = option.radius;
//allow to set password manually only when enable set pattern option is true
//permitir definir a senha manualmente somente quando a opção de padrão de configuração ativada for verdadeira
if (!option.enableSetPattern) return;
//check if pattern is string break it with the delimiter
//verifique se o padrão é uma string quebrá-lo com o delimitador
if (typeof pattern === "string") {
pattern = pattern.split(option.delimiter);
}
this.reset();
iObj.wrapLeft = 0;
iObj.wrapTop = 0;
for (var i = 0; i < pattern.length; i++) {
var idx = pattern[i] - 1,
x = idx % matrix[1],
y = Math.floor(idx / matrix[1]),
clientX = x * (2 * margin + 2 * radius) + 2 * margin + radius,
clientY = y * (2 * margin + 2 * radius) + 2 * margin + radius;
moveHandler.call(null, {
clientX: clientX,
clientY: clientY,
preventDefault: nullFunc
}, this);
}
},
//to temprory enable disable plugin
enable: function() {
var iObj = objectHolder[this.token];
iObj.disabled = false;
},
disable: function() {
var iObj = objectHolder[this.token];
iObj.disabled = true;
},
//reset pattern lock
reset: function() {
var iObj = objectHolder[this.token];
//to remove lines
iObj.pattCircle.removeClass('hovered dir s n w e s-w s-e n-w n-e');
iObj.holder.find('.patt-lines').remove();
//add/reset a array which capture pattern
iObj.patternAry = [];
//remove last Obj
iObj.lastPosObj = null;
//remove error class if added
iObj.holder.removeClass('patt-error');
},
//to display error if pattern is not drawn correct
error: function() {
objectHolder[this.token].holder.addClass('patt-error');
},
//to check the drawn pattern against given pattern
checkForPattern: function(pattern, success, error) {
var iObj = objectHolder[this.token];
iObj.rightPattern = pattern;
iObj.onSuccess = success || nullFunc;
iObj.onError = error || nullFunc;
}
};
PatternLock.defaults = {
matrix: [3, 3],
margin: 20,
radius: 25,
patternVisible: true,
lineOnMove: true,
delimiter: "|", // um delimitador entre o padrão
enableSetPattern: true,
allowRepeat: false
};
return PatternLock;
}));
;
(function(){
var PatternCreater=new PatternLock('#createPattern',{
onDraw:function(pattern){
[lock1,lock2,lock3,lock4].forEach(function(lock){
lock.checkForPattern(pattern,function(){
alert("Hoorey");
});
});
}
});
var lock1 =new PatternLock('#patternHolder1');
var lock2= new PatternLock('#patternHolder2',{lineOnMove:false});
var lock3= new PatternLock('#patternHolder3',{patternVisible:false});
var lock4= window.lock4 = new PatternLock('#patternHolder4',{radius:30,margin:20});
var lock5= new PatternLock('#patternHolder5',{matrix:[4,4]});
//var lock6= new PatternLock('#patternHolder6',{ //Definido como patternHolder7 a id o mesmo faz a duas funcoes de tracar o caminho e passar a variavel
var lock6= new PatternLock('#patternHolder7',{
mapper: function(idx){
return (idx%9) + 1;
},
// mapper: {"1:3,2:1,3:4,4:2,5:9,6:7,7:8,8:5,9:6"};//Opcao 2
//},
onDraw:function(pattern){
alert(pattern);//Jumar Mapea o Valor no cursor
}
});
var lock7 =new PatternLock('#patternHolder7',{enableSetPattern:true});
var lock5= new PatternLock('#patternHolder8',{allowRepeat : true});
}());
;
(function(){
var patternId,
captchaHolder=$('#patternCaptcha'),
patternUI;
function reloadCaptcha(){
$.ajax({
url:"http://patterncaptcha.herokuapp.com/api/getPattern",
type:'get',
dataType:"json",
crossDomain :true,
success: function(data){
patternId = data.id;
var matrix = data.matrix,
imgData = data.imageData;
if(!patternUI){
patternUI= new PatternLock('#patternUI',{
matrix : matrix,
radius:20,
margin:15
});
}
else{
patternUI.option('matrix',matrix);
}
captchaHolder.html('<img src="'+imgData+'" id="patternImage" />');
}
});
}
reloadCaptcha();
$('#refreshCaptcha').click(function(){
reloadCaptcha();
});
$('#submitCaptcha').click(function(){
$.ajax({
url:"http://patterncaptcha.herokuapp.com/api/checkPattern",
type:'get',
dataType:"json",
data:{
patternId:patternId,
pattern:patternUI.getPattern()
},
crossDomain :true,
success: function(data){
alert(data.message);
reloadCaptcha();
}
});
});
}());
;
**patternLock.css**
/*** spacings ***/
/*** font size css **/
/*flexible width*/
/*flexible height*/
/*setting font size line height and color together*/
.patt-holder {
background: #3382c0;
background-size: auto 100%;
-ms-touch-action: none;
position: relative;
}
.patt-overlay {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 20;
}
.patt-wrap {
position: relative;
cursor: pointer;
}
.patt-wrap ul,
.patt-wrap li {
list-style: none;
margin: 0;
padding: 0;
}
.patt-circ {
position: relative;
float: left;
box-sizing: border-box;
-moz-box-sizing: border-box;
}
.patt-circ.hovered {
border: 3px solid #009900;
}
.patt-error .patt-circ.hovered {
border: 3px solid #BA1B26;
}
.patt-hidden .patt-circ.hovered {
border: 0;
}
.patt-dots {
background: #FFF;
width: 10px;
height: 10px;
border-radius: 5px;
position: absolute;
top: 50%;
left: 50%;
margin-top: -5px;
margin-left: -5px;
}
.patt-lines {
border-radius: 5px;
height: 10px;
background: rgba(255, 255, 255, 0.7);
position: absolute;
transform-origin: 5px 5px;
-ms-transform-origin: 5px 5px;
/* IE 9 */
-webkit-transform-origin: 5px 5px;
}
.patt-hidden .patt-lines {
display: none;
}
#patternUI,
#patternCaptcha {
float: left;
margin: 0 20px;
}
#actionButton {
clear: both;
}
#refreshCaptcha,
#submitCaptcha {
padding: 8px 20px;
margin: 10px 20px;
}
#patternHolder7 .patt-wrap {
z-index: 10;
}
#patternHolder7 .patt-circ.hovered {
background-color: #cde2f2;
border: none;
}
#patternHolder7 .patt-circ.hovered .patt-dots {
display: none;
}
#patternHolder7 .patt-circ.dir {
background-image: url('icon-arrow.png');
background-position: center;
background-repeat: no-repeat;
}
#patternHolder7 .patt-circ.e {
-webkit-transform: rotate(0);
-moz-transform: rotate(0);
-ms-transform: rotate(0);
-o-transform: rotate(0);
transform: rotate(0);
}
#patternHolder7 .patt-circ.s-e {
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
#patternHolder7 .patt-circ.s {
-webkit-transform: rotate(90deg);
-moz-transform: rotate(90deg);
-ms-transform: rotate(90deg);
-o-transform: rotate(90deg);
transform: rotate(90deg);
}
#patternHolder7 .patt-circ.s-w {
-webkit-transform: rotate(135deg);
-moz-transform: rotate(135deg);
-ms-transform: rotate(135deg);
-o-transform: rotate(135deg);
transform: rotate(135deg);
}
#patternHolder7 .patt-circ.w {
-webkit-transform: rotate(180deg);
-moz-transform: rotate(180deg);
-ms-transform: rotate(180deg);
-o-transform: rotate(180deg);
transform: rotate(180deg);
}
#patternHolder7 .patt-circ.n-w {
-webkit-transform: rotate(225deg);
-moz-transform: rotate(225deg);
-ms-transform: rotate(225deg);
-o-transform: rotate(225deg);
transform: rotate(225deg);
}
#patternHolder7 .patt-circ.n {
-webkit-transform: rotate(270deg);
-moz-transform: rotate(270deg);
-ms-transform: rotate(270deg);
-o-transform: rotate(270deg);
transform: rotate(270deg);
}
#patternHolder7 .patt-circ.n-e {
-webkit-transform: rotate(315deg);
-moz-transform: rotate(315deg);
-ms-transform: rotate(315deg);
-o-transform: rotate(315deg);
transform: rotate(315deg);
}