3
I need to create a design password pattern for a mobile maintenance site, so that when a customer opens a service order and if your phone has screen lock it can leave recorded and if the technician needs can use.
After much searching for what seems to me but promising is the patternlock plugin. How do I pass the lock drawing to another page, and after recording in the database, I can retrieve the information leaving drawn?
Follow an example:
index.html
script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
< link href="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.js v 1.0.1
Author: Sudhanshu Yadav
Copyright (c) 2015,2016 Sudhanshu Yadav - ignitersworld.com , released under the MIT license.
Demo on: ignitersworld.com/lab/patternLock.html
*/
;(function(factory) {
/** support UMD ***/
var global = Function('return this')() || (42, eval)('this');
if (typeof define === "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);
}
Follow the example
– Junior
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script> <link href="http://ignitersworld.com/lab/assets/css/patternLock.css?33" rel="stylesheet" type="text/css"> <title> title<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
– Junior
Please edit the question by placing the full code on it. In the comment it is cut.
– Grupo CDS Informática