I need help creating a blocking pattern for Android using the patternLock plugin

3

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);
}
    
asked by anonymous 20.09.2017 / 10:42

1 answer

1

<html>
<head>
<link href="css/patternLock.css"  rel="stylesheet" type="text/css" />
<script src="js/jquery.js"></script>
<script src="js/patternLock.js"></script>
<script>
    $(document).ready(function() {
        var lock = new PatternLock("#patternHolder7", {enableSetPattern: true});
        lock.setPattern('12345');
    });
</script>

<h1>Resultado!</h1>
<div class="container">
    <div id="patternHolder7"></div>
</div>

    
21.09.2017 / 10:11