Skip to main content

Android Pattern locker plugin - Javascript

This is my new JavaScript plugin for generating Android like Pattern locker for web applications.

This is fully customizable plugin. Don't know where it can be used.... Just developed in my own interest.... please suggest some improvements for the same..... I think the captcha can be replaced with this plugin.

I have created the plugin using raphaeljs.

How to use? 

Step 1: Include the  following scripts in your head section (click here to download raphaeljs , click here to download pattern.js)
<script src="raphael-min.js" type="text/javascript"></script>
<script src="pattern.js" type="text/javascript"></script>

Step 2: Create an instance for the pattern with your custom properties and draw the pattern within the container with instance.draw(container).

var s = new Pattern(properties);
s.draw(container); 

Properties

Property Description Default Value
dimension Dimension of the patern
No. of rows x No. of columns
Eg:
dimension:‘5x5’
3x3
patternRadius Radius of the pattern circle
Eg:
patternRadius:25
20
patternGap Gap between each Pattern Circle
Eg:
patternGap:70
50
outerColor Color of the Pattern Circle. The color value can be either hex color or hex gradient color
Eg:
outerColor:’#FC0000’
outerColor :‘90-#239EE0:5-#1951A0:95’
#333333
innerColor Color of the inner circle within the Pattern Circle
Eg:
innerColor:’#FC0000’
innerColor :‘90-#239EE0:5-#1951A0:95’
90-#239EE0:5-#1951A0:95
background Pattern box background color
Eg:
background:’#FF00F0’
#000000
backgroundOpacity Pattern box background opacity
Eg:
background:0.5
1
hoverColor Stroke color of Pattern Circle when mouse over
Eg:
hoverColor:’#FF00F0’
#c8ee17
errorColor Stroke color of Pattern Circle for Invalid Pattern
Eg:
errorColor:’#FF00F0’
#FF0000
padding Pattern Box padding
Eg:
padding:25
Value of pattern radius
onFinish Handler to be executed when the user completes the pattern
Eg:
onFinish:function(value){
}
value – value of the pattern drawn passed to the handler
null

also you can set the property values externally with the created pattern Object

Functions

Function Description Return value
draw (container) Draw the pattern within the container. Should be called with pattern instance.
Eg:
s.draw(‘mydiv’);
Here ‘mydiv’ represents containerId
s.draw(document.getElementById(‘mydiv’));
Return Pattern Object
clear() Resets the pattern.
Eg:
s.clear();
Return Pattern Object
error() Used to mark the drawn pattern as error
Eg:
s.error();
Return Pattern Object
val() Used to get the value of drawn pattern
Eg:
s.val();
for the image attached in this post, the value returned will be ‘3-4-5-10-15
Return pattern value

eg:
var samplePattern = "3-4-5-10-15";
var s = new Pattern({
    dimension: '5x5',
    outerColor: '#000',
    patternRadius: 20,
    patternGap: 30,
    padding: 20,
    background: '#333',
    backgroundOpacity: 0.5
});
s.onFinish = function (v) {
    if (v == samplePattern) alert('success');
    else this.error();
};
s.draw('mypattern');


Plugin


var Pattern = function (options) {
    this.dimension = options.dimension && options.dimension.indexOf('x') !== -1 ? options.dimension.split('x') : [3, 3];

    this.patternRadius = options.patternRadius || 20;
    this.patternGap = options.patternGap || 50;
    this.innerColor = options.innerColor || '90-#239EE0:5-#1951A0:95';
    this.outerColor = options.outerColor || '#333333';
    this.background = options.background || '#000000';
    this.backgroundOpacity = options.backgroundOpacity || 1;
    this.hoverColor = options.hoverColor || '#c8ee17';

    this.errorColor = options.errorColor || '#FF0000';

    this.padding = options.padding || this.patternRadius;

    this.onFinish = options.onFinish || function (v) {};

    this.width = this.dimension[0] * (2 * this.patternRadius + this.patternGap) + (this.padding * 4) - this.patternGap;
    this.height = this.dimension[1] * (2 * this.patternRadius + this.patternGap) + (this.padding * 4) - this.patternGap;

    this.paper = null;
    this.patternCircle = [];
    this.value = [];
    this.blocker = null;

    var patternObj = this;
    this.isMouseDown = false;
    this.lineX = 0;
    this.lineY = 0;
    this.currentPath = null;
    this.currentTarget = null;


    //styes
    this.paperStyle = {
        fill: patternObj.background,
            'stroke-width': 0,
        opacity: patternObj.backgroundOpacity
    };
    this.selectedStyle = {
        'fill': '#CCC',
            'fill-opacity': 0.3,
            'stroke-width': 3,
            'stroke': '#C8E02A'
    };
    this.innerStyle = {
        'fill': patternObj.innerColor,
            'stroke-width': 0
    };
    this.outerStyle = {
        'fill': patternObj.outerColor,
            'stroke-width': 0,
            'fill-opacity': 1,
    };
    this.hoverStyle = {
        'stroke-width': 3,
            'stroke': patternObj.hoverColor,
            'stroke-opacity': 1
    };
    this.pathStyle = {
        stroke: '#FFF',
            'stroke-width': '5',
            'stroke-linecap': 'round',
            'opacity': 0.3
    };
    this.errorStyle = {
        'stroke-width': 3,
            'stroke': patternObj.errorColor,
            'stroke-opacity': 0.75
    };

    //common handlers
    var paperMouseUpHandler = function () {
        patternObj.isMouseDown = false;
        if (patternObj.currentPath) {
            patternObj.currentPath.remove();
        }
        if (patternObj.currentTarget.length && patternObj.currentTarget[0].data('connection') == 1) {
            patternObj.blocker = patternObj.paper.rect(0, 0, patternObj.width, patternObj.height, patternObj.patternRadius).attr({
                fill: '#000',
                    'stroke-width': 0,
                    'fill-opacity': 0
            });
        }
        patternObj.currentPath = [];
        patternObj.currentTarget = [];

        if (typeof (patternObj.onFinish)) {
            patternObj.onFinish(patternObj.val());
        }
    };

    var drawPathHandler = function (e) {
        e = e || window.event;

        var pX = e.pageX;
        var pY = e.pageY;
        if (pX === undefined) {
            pX = e.clientX;
            pY = e.clientY;
        }
        pX = pX - ((window.pageXOffset || document.body.scrollLeft) + patternObj.paper.canvas.getBoundingClientRect().left);
        pY = pY - ((window.pageYOffset || document.body.scrollTop) + patternObj.paper.canvas.getBoundingClientRect().top);

        e.stopPropagation();
        if (patternObj.isMouseDown && patternObj.currentPath) {
            patternObj.currentPath.attr('path', "M" + patternObj.lineX + " " + patternObj.lineY + "L" + pX + " " + pY);
        }
    };

    this.disableSelection = function (target) {
        if (typeof target.onselectstart != "undefined") {
            target.onselectstart = function () {
                return false
            };
        } else if (typeof target.style.MozUserSelect != "undefined") {
            target.style.MozUserSelect = "none";
        } else {
            target.onmousedown = function () {
                return false
            };
        }
    };

    this.createPattern = function (paperObj) {
        var x = 0,
            y = 0,
            i, j, elm = null;
        for (i = 0; i < patternObj.dimension[0]; i++) {
            x = i * (patternObj.patternGap + patternObj.patternRadius * 2) + patternObj.padding + patternObj.patternRadius;
            for (j = 0; j < patternObj.dimension[1]; j++) {
                y = j * (patternObj.patternGap + patternObj.patternRadius * 2) + patternObj.patternRadius + patternObj.padding;
                elm = patternObj.drawPatternPoint(paperObj, x, y, i, j);
                patternObj.patternCircle.push(elm);
                elm[0].data({
                    x: i,
                    y: j
                });
            }
        }
        patternObj.sort();
    };

    this.sort = function () {
        var i, j, tmpAry = [],
            elm, cnt = 1;
        for (i = 0; i < patternObj.dimension[1]; i++) {
            for (j = 0; j < patternObj.dimension[0]; j++) {
                elm = patternObj.getByXY(j, i);
                elm[0].data({
                    'value': cnt
                });
                elm[1].data({
                    'value': cnt
                });
                tmpAry.push(elm);
                cnt++;
            }
        }
        patternObj.patternCircle = tmpAry;
    };

    this.drawConnection = function (oCircle, iCircle, currentTarget) {
        patternObj.currentPath.attr('path', "M" + patternObj.lineX + " " + patternObj.lineY + "L" + (oCircle.getBBox().x + oCircle.getBBox().width / 2) + " " + (oCircle.getBBox().y + oCircle.getBBox().height / 2));
        patternObj.lineX = (oCircle.getBBox().x + oCircle.getBBox().width / 2);
        patternObj.lineY = (oCircle.getBBox().y + oCircle.getBBox().height / 2);

        patternObj.currentPath = patternObj.paper.path("M" + patternObj.lineX + " " + patternObj.lineY + "L" + patternObj.lineX - 2 + " " + patternObj.lineY - 2).attr(patternObj.pathStyle);
        patternObj.currentPath.mouseup(paperMouseUpHandler);
        currentTarget.data({
            'connection': 1
        }).attr(patternObj.selectedStyle);
        iCircle.data({
            'connection': 1
        });
        oCircle.data({
            'connection': 1
        }).attr(patternObj.selectedStyle);
        patternObj.value.push(oCircle.data('value'));
    };

    this.getByXY = function (x, y) {
        for (var i = 0; i < this.patternCircle.length; i++) {
            if (this.patternCircle[i][0].data('x') == x && this.patternCircle[i][0].data('y') == y) {
                return this.patternCircle[i];
            }
        }
        return null;
    };

    this.drawPatternPoint = function (paperObj, x, y, xi, yi) {
        var patternElm = paperObj.set();
        var oCircle = paperObj.circle(patternObj.padding + x, patternObj.padding + y, patternObj.patternRadius).attr(patternObj.outerStyle);
        var iCircle = paperObj.circle(patternObj.padding + x, patternObj.padding + y, patternObj.patternRadius / 3).attr(patternObj.innerStyle);
        iCircle.data({
            'connection': 0,
                'x': xi,
                'y': yi
        });
        oCircle.data({
            'connection': 0,
                'x': xi,
                'y': yi
        });

        patternElm.push(oCircle, iCircle);

        var patternMousemoveHandler = function (e) {
            oCircle.attr(patternObj.hoverStyle);

            if (patternObj.currentPath && (patternObj.currentTarget[0] !== oCircle[0] && patternObj.currentTarget[1] !== iCircle[0]) && (iCircle.data('connection') == 0)) {

                var x1 = patternObj.currentTarget[0].data('x');
                var y1 = patternObj.currentTarget[0].data('y');
                var x2 = oCircle.data('x');
                var y2 = oCircle.data('y');

                var xs = x1 > x2 ? x2 : x1;
                var xe = x1 > x2 ? x1 : x2;
                var ys = y1 > y2 ? y2 : y1;
                var ye = y1 > y2 ? y1 : y2;

                var i, j;
                var telm = null;
                var connect = function (a, b) {
                    telm = patternObj.getByXY(a, b);
                    if (telm[0].data('connection') == 0) {
                        patternObj.drawConnection(telm[0], telm[1], telm[0]);
                    }
                };
                if (x1 == x2 && y1 !== y2) {
                    if (y1 < y2) {
                        for (i = ys; i <= ye; i++) {
                            connect(xs, i);
                        }
                    } else {
                        for (i = ye; i >= ys; i--) {
                            connect(xs, i);
                        }
                    }
                } else if (y1 == y2 && x1 !== x2) {
                    if (x1 > x2) {
                        for (i = xe; i >= xs; i--) {
                            connect(i, ys);
                        }
                    } else {
                        for (i = xs; i <= xe; i++) {
                            connect(i, ys);
                        }
                    }
                } else if (Math.abs(x1 - x2) == Math.abs(y1 - y2)) {
                    for (i = 0; i <= Math.abs(ys - ye); i++) {
                        if (y1 < y2 && x1 > x2) {
                            connect(x1 - i, y1 + i);
                        } else if (y1 > y2 && x1 < x2) {
                            connect(x1 + i, y1 - i);
                        } else if (y1 < y2) {
                            connect(x1 + i, y1 + i);
                        } else {
                            connect(x1 - i, y1 - i);
                        }
                    }
                }
                patternObj.currentTarget.pop();
                patternObj.currentTarget = [oCircle, iCircle];
            }

        };

        var patternMouseoutHandler = function () {
            if (oCircle.data('connection') == 0) {
                oCircle.attr({
                    'stroke-width': 0
                });
            }
        };

        var patternMouseDownHandler = function (e) {
            patternObj.isMouseDown = true;
            patternObj.currentTarget = [oCircle, iCircle];
            patternObj.lineX = patternElm.getBBox().x + patternElm.getBBox().width / 2;
            patternObj.lineY = patternElm.getBBox().y + patternElm.getBBox().height / 2;
            patternObj.currentPath = patternObj.paper.path("M" + patternObj.lineX + " " + patternObj.lineY + "L" + patternObj.lineX - 2 + " " + patternObj.lineY - 2).attr(patternObj.pathStyle);
            patternObj.currentPath.touchend(paperMouseUpHandler);
            patternObj.currentPath.mouseup(paperMouseUpHandler);
        };

        patternElm.mousemove(patternMousemoveHandler);
        patternElm.mouseout(patternMouseoutHandler);
        patternElm.mousedown(patternMouseDownHandler);
        patternElm.mouseup(paperMouseUpHandler);
        return [oCircle, iCircle];
    };

    this.drawPaper = function (elm) {
        var paper = Raphael(elm, patternObj.width, patternObj.height);
        var rect = paper.rect(0, 0, patternObj.width, patternObj.height, patternObj.patternRadius).attr(patternObj.paperStyle);
        rect.mousemove(drawPathHandler);
        rect.mouseup(paperMouseUpHandler);
        return paper;
    };

    this.draw = function (elm) {
        patternObj.paper = patternObj.drawPaper(elm);
        patternObj.createPattern(this.paper);
        patternObj.disableSelection(patternObj.paper.canvas);
        return this;
    };

    this.clear = function () {
        var paths = patternObj.paper.canvas.getElementsByTagName('path');
        var cnt = paths.length;
        for (var i = 0; i < cnt; i++) {
            paths[0].parentNode.removeChild(paths[0]);
        }
        patternObj.paper.forEach(function (el) {
            if (el[0].tagName.toLowerCase() == 'circle') {
                el.data({
                    'connection': 0
                });
                if (patternObj.patternRadius == el.attr('r')) {
                    el.attr(patternObj.outerStyle);
                }
            }
        });
        if (patternObj.blocker) {
            patternObj.blocker.remove();
        }
        patternObj.blocker = null;
        patternObj.currentPath = null;
        patternObj.currentTarget = [];
        patternObj.value = [];
        
        return this;
    };

    this.error = function () {
        for (var i = 0; i < patternObj.patternCircle.length; i++) {
            if (patternObj.patternCircle[i][0].data('connection') == 1) {
                patternObj.patternCircle[i][0].attr(patternObj.errorStyle);
            }
        }
        
        return this;
    };

    this.val = function () {
        return patternObj.value.toString().replace(/,/g, '-');
    };
};

Comments

Popular posts from this blog

RGB in C

Default palette size for normal graphics driver is 16 i.e) the color number rages from 0 to 15 To use rgb color modes we have to choose VGA or IBM 8514 as a graphics driver For VGA, Palette size is 16 i.e) color number ranges from 0-16 For IBM 8514, Palette size is 256 i.e) color number ranges from 0-255, we can also say it as VGA with 256 palette size By using setrgbpalette function we can generate RGB colors, we can generate colors with respect to Palette size. This function replaces the default palette colors with the generated Palette colors. Syntax: void setrgbpalette(int colornum, int red, int green, int blue); /* colornum - color number in palette (0-15 or 0-255 depens on graphics driver) red - color value for red (0-255) green - color value for green (0-255) blue - color value for blue (0-255) */ Example: #include<graphics.h> #include<stdio.h> #include<conio.h> #include<stdlib.h> #include<time.h> void main(){ int gd=VGA,

Simple Animation Using C

Here i have used fillpoly function to draw the object body and used fillellipse function to draw tier. animation is done by looping through the objects x & y position until user hits a key. Keypress event is achived  by using kbhit function. Smoothness of animation is controlled by delay function. Change the delay values to change the animation speed Source: #include<stdio.h> #include<conio.h> #include<graphics.h> #include<dos.h> void main() { int gd=DETECT,gm,i=-300,j; int poly[16]={100,100,250,100,250,50,300,50,325,90,325,140,100,140,100,100}; int tpoly[16]={100,100,250,100,250,50,300,50,325,90,325,140,100,140,100,100}; initgraph(&gd,&gm,""); getch(); while(!kbhit()) { for(j=0;j<16;j+=2) { poly[j]=tpoly[j]+i; } fillpoly(8,poly); setfillstyle(5,7); bar(275+i,60,295+i,85); setfillstyle(5,8); fillellipse(140+i,140,20,20); fillellipse(280+i,140,20,20); setfillstyle(1,0); fillellipse(140+i,140,10,10); fillellipse(280+i,140,10

Random Bouncing Ball Animation

Simple animation of random balls that bounces within the screen Source: #include<stdio.h> #include<graphics.h> #include<conio.h> #include<dos.h> #include<math.h> void drawBall(struct ball *b, int color); struct ball{ int x, y; int dx, dy; int radius; }; void main() { int gd=0, gm=VGAHI; int i; struct ball b[10]; initgraph(&gd, &gm, ""); for(i=1;i<=15;i++){ b[i].radius = rand()%20; b[i].x=rand()%getmaxx(); b[i].y=rand()%getmaxy(); b[i].dx=2; b[i].dy=4; } while(!kbhit()) { delay(5); cleardevice(); for(i=1;i<=15;i++) drawBall(&b[i],i); } closegraph(); } void drawBall(struct ball *b, int color){ setfillstyle(1,color); setcolor(color); fillellipse(b->x, b->y, b->radius, b->radius); if(b->x+b->radius > getmaxx() || b->x-b->radius<0) b->dx = -b->dx; if(b->y+b->radius > getmaxy() || b->y-b->radius<0) b->dy = -b->dy; b->x+=b-&g