I need help to create a type lock pattern for Android using the patternLock plugin

Asked

Viewed 83 times

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

  • <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

  • Please edit the question by placing the full code on it. In the comment it is cut.

1 answer

1

Personal follows below the solution to the problem I was trying, breaking a little the head this there, very useful this function.

<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>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.