awesome Mosaic menu

This is a great application, very useful code.I believe you will like it.

 

 

css

html {
overflow: hidden;
}
body {
position: absolute;
margin: 0px;
padding: 0px;
width: 100%;
height: 100%;
background:#000;
}
#screen {
position: absolute;
width: 891px;
height: 550px;
left: 50%;
top: 50%;
margin-left:-445px;
margin-top:-275px;
background: #111;
overflow: hidden;
}
#screen .grid {
position: absolute;
background: #333;
font-size: 0px;
overflow: hidden;
}
#screen .txt {
position: absolute;
font-size: 14px;
color: #fff;
font-family: arial;
overflow: hidden;
}
#screen .menu {
position: absolute;
font-size: 12px;
color: #fff;
font-family: arial;
overflow: hidden;
cursor: pointer;
}
#screen .menubackgroundcolor {
opacity: 0.7;
filter: alpha(opacity=70);
}
#screen .wrapper {
position:absolute;
left: 2%;
top: 2%;
width: 96%;
height: 96%;
overflow: hidden;
}
#screen .wrapper img {
float: left;
margin-right: 6px;
margin-bottom: 0px;
}
#screen h1 {
position:relative;
top: 20px;
width: 100%;
text-align: center;
letter-spacing: 0px;
font-size: 2.5em;
}
#screen .menucontent {
position: absolute;
width: 100%;
text-align: center;
font-size: 128px;
letter-spacing: 0px;
font-weight: bold;
top: -10px;
}
#screen .submenucontent {
position: absolute;
width: 100%;
height: 100%;
}

#screen .submenutitle {
position: absolute;
top: -12px;
font-size: 64px;
font-weight: bold;
}
#screen .submenu {
position: absolute;
width: 100%;
top: 55px;
}

#screen .submenuline {
position: relative;
height: 18px;
font-size: 14px;
margin-top: 1px;
}

#screen .lineover {
background: #fff;
color: #0064a0;
font-weight: bold;
}

#loader {
position:absolute;
left: 50%;
top: 50%;
width: 50px;
margin-left: -25px;
margin-top: -14px;
text-align: center;
font-family: arial;
font-size: 24px;
font-weight: bold;
color: #fff;
background: #000;
outline: #111 solid 3px;
opacity: 0.6;
filter: alpha(opacity=60);
z-index: 1000;
}
#htmlBank {
display: none;
visibility: hidden;
}

javascript


var dp = function ()
{
// private variables
var object = {
cell: [],
menu: [],
text: []
},
scr, imagesPath, params, fullImage, loader,
P, Pn, Pt, lastMenuOver, pc, backgroundImage,
preload, mibar, nx, ny, nw, nh, sw, sh;

/* ===== append HTML Element function ==== */
var appendHTML = function (p)
{
var i, object = document.createElement(p.tagName);   // create HTML element
for (i in p.attributes) object[i] = p.attributes[i]; // copy attributes
for (i in p.style) object.style[i] = p.style[i];     // copy style properties
if (p[removed]) p[removed].appendChild(object);  // insert object
return object;
};
/* ===== copy JS object ==== */
var clone = function (obj)
{
if (typeof(obj) != "object" || obj == null) return obj;
var newObj = obj.constructor();
for (var i in obj) newObj[i] = clone(obj[i]);
return newObj;
}
/* ==== text constructor ==== */
var Text = function ()
{
// text content
this.div = appendHTML({
parentNode: scr,
tagName: "div",
attributes:
{
className: "txt",
onmouseover: function () { hideLastMenu(); }
}
});
this.css = this.div.style;
};

Text.prototype =
{
/* ==== start typewriter ==== */
startTypewriter: function (t)
{
this.k = 0;
this.html = t.id ? (
document.getElementById(t.id) ?
document.getElementById(t.id)[removed] : t.id + " undefined"
) : t.html + " ";
this.html = this.html.replace(/n/g, "");
this.l    = this.html.length;
this.css.visibility = "visible";
this.css.left       = Math.round(t.x * sw) + "px";
this.css.top        = Math.round(t.y * sh) + "px";
this.css.width      = Math.round(t.w * sw) + "px";
this.css.height     = Math.round(t.h * sh) + "px";
this.div[removed]  = "";
// typewriter loop
var self = this;
this.interval = setInterval(
function () { self.typeLoop(); }
, 32);
},

/* ==== skip HTML tag ==== */
skipTag: function()
{
if (this.html.charAt(this.k) === "<")
this.k += this.html.slice(this.k).indexOf(">") + 1;
},

/* ==== typewriter loop ==== */
typeLoop: function ()
{
if (this.k <= this.l)
{
this.skipTag();
var n = this.html.slice(this.k).indexOf(" ");
this.k += (n >= 0) ? n : 1;
this.skipTag();
this.div[removed] = this.html.slice(0, this.k++);
}
else
{
clearInterval(this.interval);
this.interval = false;
}
}
};

/* ==== menu constructor ==== */
var Menu = function (n, p)
{
// menu wrapper
this.div = appendHTML({
parentNode: scr,
tagName: "div",
attributes:
{
parent: this,
className: "menu",
onclick: function () { this.parent.click(); },
onmouseover: function () { this.parent.over(); }
},
style: { visibility: "hidden" }
});
// Color backround
var bgc = appendHTML({
parentNode: this.div,
tagName: "div",
attributes: { className: "menubackgroundcolor" },
style: { position: "absolute" }
});
this.bgc = bgc.style;
// menu container
this.menuDiv = appendHTML({
parentNode: this.div,
tagName: "div",
attributes:
{
parent: this,
className: "menucontent",
innerHTML: p.html,
onclick: function () { this.parent.click(); },
onmouseover: function () { this.parent.over(); }
}
});

this.css = this.div.style;
this.pageTarget = p.target;

// sub menu construction
if (p.submenu)
{
this.submenuDiv = appendHTML({
tagName: "div",
parentNode: this.div,
attributes: { className: "submenucontent" },
style: { visibility: "hidden" }
});

// title
if (p.submenu.title)
{
appendHTML({
parentNode: this.submenuDiv,
tagName: "div",
attributes:
{
className: "submenutitle",
innerHTML: p.submenu.title,
onclick: function () {
resetLoops();
Pt = P.text;
displayPage();
return false;
}
}
});
}

// submenu container
this.submenuContent = appendHTML({
parentNode: this.submenuDiv,
tagName: "div",
attributes: { className: "submenu" }
});

// submenu lines
this.menuitem = [];
var i = 0, o;
while (o = p.submenu.lines[i++])
{
this.menuitem.push(
new Submenuitem(this, o)
);
}
}
};

Menu.prototype =
{
/* ==== menu over ==== */
over: function ()
{
if (this.pageTarget != Pn && lastMenuOver != this)
{
hideLastMenu();
lastMenuOver = this;
this.menuDiv.style.visibility = "visible";
/* ---- flash ---- */
this.c = clone(params.flash);
var self = this, k = 0;
var overflash = function ()
{
if (k++ < 12)
{
self.fadeColor(0.2);
setTimeout(overflash, 32);
}
else self.fadeColor(0);
};
overflash();
}
},

/* ==== menu click ==== */
click: function ()
{
var t = this.pageTarget;
if (t !== Pn && params.page[t])
{
// new page
resetLoops();
Pn = t;
P = params.page[t];
Pt = P.text;
displayPage();
}
},

/* ==== target move ==== */
move: function (i)
{
// targets
this.xt = P.menuTarget[i].x;
this.yt = P.menuTarget[i].y;
this.ct = clone(P.menuBackgroundColor);
// init menu dimension
this.css.visibility = "visible";
this.css.width      = this.bgc.width = Math.round(sw - 1) + "px";
this.css.height     = this.bgc.height = Math.round(sh - 1) + "px";
// content visibility
this.menuDiv.style.visibility = (this.pageTarget === Pn) ? "visible" : "hidden";
if (this.submenuDiv) this.displayMenuitem(false);
// moving menu loop
var self = this;
this.interval = setInterval(
function () { self.moving(); }
, 32);
},

fadeColor: function (speed)
{
// transition
if (speed)
{
this.c.r += (this.ct.r - this.c.r) * speed;
this.c.g += (this.ct.g - this.c.g) * speed;
this.c.b += (this.ct.b - this.c.b) * speed;
}
else this.c = clone(this.ct);
// HTML background color
this.bgc.backgroundColor = "RGB("
+ Math.round(this.c.r) + ","
+ Math.round(this.c.g) + ","
+ Math.round(this.c.b) + ")";
},
/* ==== move ==== */
moving: function ()
{
// distance to target
var speed = 0;
var dx = this.xt - this.x;
var dy = this.yt - this.y;
if (Math.abs(dx) > 0.01 || Math.abs(dy) > 0.01)
{
// inc position
this.x += dx * .2;
this.y += dy * .2;
speed = 0.1;
}
else
{
// init values
this.x = this.xt;
this.y = this.yt;
// stop animation
clearInterval(this.interval);
// submenu
if (this.submenuDiv && this.pageTarget === Pn)
{
// display submenu
this.menuDiv.style.visibility = "hidden";
this.displayMenuitem(true);
}
}
// update HTML
this.css.left = Math.round(this.x * sw) + "px";
this.css.top  = Math.round(this.y * sh) + "px";
this.fadeColor(speed);
},

/* ---- show menu items ---- */
displayMenuitem: function (visible)
{
var i = 0, o, menuitem = this.menuitem;
while (o = menuitem[i++]) o.div.style.visibility = "hidden";
this.submenuDiv.style.visibility = "hidden";
if (visible)
{
i = 0;
this.submenuEnabled = true;
var self = this;
var displayMenuitem = function ()
{
var o = menuitem[i++];
if (o && self.submenuEnabled)
{
o.div.style.visibility = "visible";
// complementary bar colors
o.bar.style.background = "RGB(" +
Math.round((256 - P.menuBackgroundColor.r) * 0.25) + "," +
Math.round((256 - P.menuBackgroundColor.g) * 0.25) + "," +
Math.round((256 - P.menuBackgroundColor.b) * 0.25) + ")";
setTimeout(displayMenuitem, 64);
}
};
setTimeout(displayMenuitem, 256);
this.submenuDiv.style.visibility = "visible";
} else this.submenuEnabled = false;
}
};

/* ==== sub menu item constructor ==== */
var Submenuitem = function (parent, p)
{
this.parent = parent;
this.text = p.text;
this.k = 100;
this.fullImage = p.fullImage;
this.div = appendHTML({
tagName: "div",
parentNode: parent.submenuContent,
attributes:
{
className: "submenuline",
parent: this,
onclick:     function () { this.parent.click(); },
onmouseover: function () { this.parent.over(); }
}
});
this.bar = appendHTML({
tagName: "div",
parentNode: this.div,
style:
{
position: "absolute",
width: "100%",
height: "100%",
left: "100%"
}
});
this.txt = appendHTML({
tagName: "div",
parentNode: this.div,
attributes:
{
innerHTML: p.html
},
style:
{
position: "absolute",
marginLeft: "10px"
}
});
};

/* ---- menu items functions ---- */
Submenuitem.prototype =
{
/* ---- select ---- */
click: function ()
{
resetLoops();
resetText();
Pt = this.text;
if (this.fullImage)
{
// display full image
fullImage = this.fullImage;
displayPage();
}
// update text
else nextText();
},

/* ---- bar left ---- */
over: function ()
{
mibar = this;
var i = 0, o;
while (o = this.parent.menuitem[i++]) if (o != this && !o.r) o.out();
var self = this;
this.r = false;
var barLeft = function ()
{
if (self === mibar)
{
self.bar.style.left = Math.round(self.k *= .25) + "%";
if (Math.round(self.k) > 0) setTimeout(barLeft, 32);
}
};
barLeft();
},

/* ---- bar right ---- */
out: function ()
{
if (this.k < 100)
{
if (this.k < 1) this.k = 1;
var self = this;
this.r = true;
var barRight = function ()
{
self.bar.style.left = Math.round(self.k *= 2) + "%";
if (Math.round(self.k) < 100) setTimeout(barRight, 32);
};
barRight();
}
}
};

/* ==== cell constructor ==== */
var Cell = function (n, x, y)
{
this.n  = n;
this.x0 = x;
this.y0 = y;
// next directions
this.dir = [
(x - 1 >= 0 ? n - ny : n),
(x + 1 < nx - 1 ? n + ny : n),
(y - 1 >= 0 ? n - 1 : n),
(y + 1 < ny - 1 ? n + 1 : n)
];

// fade in-out div
this.opc = appendHTML({
parentNode: scr,
tagName: "div",
attributes:
{
onmouseover: function () { hideLastMenu(); }
},
style:
{
position: "absolute",
filter: "alpha(opacity=100)",
opacity: 1,
background: "#000",
left:   Math.round(x * sw) + "px",
top:    Math.round(y * sh) + "px",
width:  Math.round(sw - 1) + "px",
height: Math.round(sh - 1) + "px"
}
});

// white flash div
this.fla = appendHTML({
parentNode: scr,
tagName: "div",
style:
{
position: "absolute",
background: "#fff",
visibility: "hidden",
left:   Math.round(x * sw) + "px",
top:    Math.round(y * sh) + "px",
width:  Math.round(sw - 1) + "px",
height: Math.round(sh - 1) + "px"
}
});

// grid horizontal
if (x == 0 && y > 0)
{
this.hor = appendHTML({
parentNode: scr,
tagName: "div",
attributes: { className: "grid" },
style:
{
top: Math.round(y * sh - 1) + "px",
width: nw + "px",
height: "1px"
}
});
}
// grid vertical
if (y == 0 && x > 0)
{
this.ver = appendHTML({
parentNode: scr,
tagName: "div",
attributes: { className: "grid" },
style:
{
left: Math.round(x * sw - 1) + "px",
width: "1px",
height: nh + "px"
}
});
}
};

Cell.prototype =
{
/* ==== crossbrowser opacity function ==== */
opacity: function (alpha)
{
if (this.opc.filters && this.opc.filters.alpha)
{
// redefine function for IE<9
Cell.prototype.opacity = function (alpha)
{
this.opc.filters.alpha.opacity = Math.round(alpha);
};
this.opacity(alpha);
}
else
{
// redefine function for CSS3
Cell.prototype.opacity = function (alpha)
{
this.opc.style.opacity = alpha * 0.01;
};
this.opacity(alpha);
}
},

/* ==== display image ==== */
displayCell: function ()
{
// mark cell as displayed
this.displayed = true;
// flash
this.fla.style.visibility = "visible";
// fading loop
var self = this;
this.interval = setInterval(
function () { self.displayCellLoop(); }
, 32);
},

/* ==== display cell loop ==== */
displayCellLoop: function ()
{
var o;
if (this.alpha !== this.alphaTarget)
{
// opacity
this.alpha += this.step;
this.opacity(this.alpha);
// find next cell
if (this.alpha === this.nextCell)
{
var i = 0,
s = false;
while (i++ < 8)
{
o = object.cell[
this.dir[Math.floor(Math.random() * 4)]
];
// cell is available
if (!o.displayed)
{
o.displayCell();
s = true;
break;
}
}
if (!s)
{
// find new starting point
o = startingCell();
if (o !== false) o.displayCell(); // next cell
else this.startNext = true; // the end
}
}
// stop flash
if (this.alpha === this.endFlash) this.fla.style.visibility = "hidden";
if (this.startNext && this.alpha === this.nextStep)
{
// start typeWriter
if (this.txt && (this.id || this.html)) object.text[pc].startTypewriter(this);
// next phase
if (P.text[pc] && !fullImage) nextText();
}
}
else
{
// stop animation loop
clearInterval(this.interval);
this.interval = false;
this.fla.style.visibility = "hidden";
}
}
};

/* ==== return random available cell ==== */
var startingCell = function ()
{
var o, i = 0, avail = [];
while (o = object.cell[i++]) if (!o.displayed) avail.push(o);
if (!avail.length) return false; // no available cell
else
{
// return random available cell
return avail[
Math.floor(Math.random() * avail.length)
];
}
};

/* ==== initialize cells ==== */
var initCell = function (p, fx, txt)
{
var i = 0, o;
while (o = object.cell[i++])
{
// is Cell active
if (o.x0 >= p.x && o.x0 <= (p.x + p.w - 1) &&
o.y0 >= p.y && o.y0 <= (p.y + p.h - 1))
{
// copy variables
o.displayed = false;
o.startNext = false;
o.id = false;
o.txt = txt;
for (var j in p)  o[j] = p[j];
for (var k in fx) o[k] = fx[k];
}
}
};

/* ==== reset text ==== */
var resetText = function ()
{
// reset text containers
pc = 0;
var i = 0, o;
while (o = object.text[i++])
{
o.div[removed] = "";
o.css.visibility = "hidden";
}
// reset opacity
i = 0;
while (o = object.cell[i++])
{
o.t = true;
o.opacity(0);
}
};

/* ==== display next bloc text ==== */
var nextText = function ()
{
var o = Pt[pc++];
if (o)
{
initCell(o, params.fadeout, true);
o = startingCell();
o.displayed = true;
o.displayCell();
}
};

/* ==== menu mouse out ==== */
var hideLastMenu = function ()
{
if (lastMenuOver)
{
lastMenuOver.menuDiv.style.visibility = "hidden";
lastMenuOver = false;
}
};

/* ==== reset setIntervals ==== */
var resetLoops = function ()
{
if (preload) {
clearInterval(preload);
preload = false;
}
var i, j, k, o;
for (j in object)
{
k = object[j];
i = 0;
while (o = k[i++])
{
if (o.interval)
{
// stop loop
clearInterval(o.interval);
o.interval = false;
// stop flash
if (o.fla) o.fla.style.visibility = "hidden";
}
}
}
};

/* ==== images display sequence ==== */
var displayPage = function ()
{
var i, j, m, o;
// reset
lastMenuOver = false;
resetText();
if (!fullImage)
{
// move Menus
i = 0;
while (o = object.menu[i]) o.move(i++);
// background images
var img = P.backgroundImage;
}
else
{
// full Image
var img = fullImage;
// hide Menus
i = 0;
while (o = object.menu[i++]) o.css.left = "-1000px";
}
// preload image
var timeout    = params.timeout;
var preloadImg = new Image();
preloadImg.src = imagesPath + img;
/* ---- loading function ---- */
var preloading = function ()
{
if ((preloadImg.complete && preloadImg.width) || timeout === 0)
{
// load complete - hide loader
loader[removed] = "";
loader.style.visibility = "hidden";
// hide image
var i = 0, o;
while (o = object.cell[i++])
{
o.opacity(100);
if (fullImage)
{
// close full image
o.opc.style.cursor = "pointer";
o.opc.onclick = function ()
{
resetLoops();
fullImage = false;
Pt = P.text;
displayPage();
}
}
else
{
o.opc.style.cursor = "default";
o.opc.onclick = null;
}

}
// display background image
var css = backgroundImage.style;
if (timeout > 0)
{
backgroundImage.src = imagesPath + img;
css.left = Math.round((nw - preloadImg.width) * 0.5) + "px";
css.top  = Math.round((nh - preloadImg.height) * 0.5) + "px";
css.visibility = "visible";
}
else css.visibility = "hidden";
setTimeout(function() {
// display image  
initCell(
{
x: 0,
y: 0,
w: nx,
h: ny
},
params.fadein, false
);
// random starting point
o = startingCell();
o.displayed = true;
o.displayCell();
}, 64);
}
else
{
// waiting
timeout--;
if (timeout < params.timeout - 3)
{
// display ajax loader
loader.style.visibility = "visible";
loader[removed] = (params.timeout - timeout - 3);
}
preload = setTimeout(preloading, 64);
}
};
preloading();
};

////////////////////////////////////////////////////////////////////////////

/* ==== screen dimensions ==== */
var resize = function ()
{
nw = scr.offsetWidth;
nh = scr.offsetHeight;
sw = Math.round(nw / nx);
sh = Math.round(nh / ny);
};

/* ==== init script ==== */
var init = function (p)
{
var k, i, j, o;
params = p;
scr = document.getElementById(p.containerID);
nx = p.gridX;
ny = p.gridY;
imagesPath = p.imagesPath;
Pn = 0;
P  = p.page[Pn];
Pt = P.text;
resize();
// create background image
backgroundImage = appendHTML({
parentNode: scr,
tagName: "img",
style:
{
position: "absolute",
visibility: "hidden"
}
});
// ajax loader
loader = appendHTML({
parentNode: scr,
tagName: "div",
attributes: { id: "loader" },
style: { visibility: "hidden" }
});
// create cells
k = 0;
for (i = 0; i < nx; i++)
{
for (j = 0; j < ny; j++)
{
object.cell.push(
new Cell(k++, i, j)
);
}
}
// create txt objects
for (i = 0; i < 6; i++)
{
object.text.push(
new Text()
);
}
// create menu objects
i = 0;
while (o = p.menu[i])
{
object.menu.push(
new Menu(i++, o)
);
}
// load first page
setTimeout(
function () { displayPage(); }
, 250);
};
return {
// initialize script
init : init
}
}();

/* ==== script parameters ==== */
setTimeout(function ()
{
dp.init(
{
containerID: "screen",
gridX: 6,
gridY: 4,
imagesPath: "../images/",
timeout: 153, // 10 seconds
flash: { r: 255, g: 255, b: 255},
fadein:
{
alpha: 100,
alphaTarget: 0,
step: -5,
endFlash: 80,
nextCell: 90,
nextStep: 0,
},
fadeout:
{
alpha: 0,
alphaTarget: 60,
step: 5,
endFlash: 20,
nextCell: 10,
nextStep: 40,
},
menu: [
{
html: '1',
target: 0
},
{
html: '2',
target: 1,
submenu: {
title: '2.dö',
lines: [
{
html: 'klinükols',
text: [{
html: '',
x: 0, y: 2, w: 5, h: 1
},
{
id: "thumb1",
x: 2, y: 0, w: 1, h: 4
}]
},
{
html: 'temakäd',
text: [{
html: ' ',
x: 4, y: 0, w: 1, h: 4
},
{
id: "thumb2",
x: 0, y: 2, w: 5, h: 1
}]
},
{
html: 'hidünana',
text: [{
html: ' ',
x: 2, y: 0, w: 1, h: 4
},
{
html: ' ',
x: 4, y: 0, w: 1, h: 4
},
{
id: "thumb3",
x: 2, y: 1, w: 3, h: 2
}]
},
{
html: 'osämikebobs',
fullImage: "eve06.jpg"
}
]
}
},
{
html: '3',
target: 2
},
{
html: '4',
target: 3
}
],
page: [
{ // page 1
backgroundImage: "eve01.jpg",
menuBackgroundColor: { r: 0, g: 100, b: 160 },
text: [
{
html: ' ',
x: 0, y: 2, w: 2, h: 2
},
{
id: "txt1",
x: 4, y: 1, w: 2, h: 2
},
{
html: '

büdolös

',
x: 4, y: 3, w: 1, h: 1
}
],
menuTarget: [
{ x: 0, y: 0 },
{ x: 1, y: 1 },
{ x: 0, y: 3 },
{ x: 5, y: 3 }
]
},
{ // page 2
backgroundImage: "eve02.jpg",
menuBackgroundColor: { r: 102, g: 102, b: 51 },
text: [{
html: ' ',
x: 5, y: 3, w: 1, h: 1
},
{
html: ' ',
x: 0, y: 3, w: 1, h: 1
},
{
id: "txt2",
x: 0, y: 0, w: 3, h: 2
},
{
html: '

kanaänik

',
x: 5, y: 0, w: 1, h: 1
}
],
menuTarget: [
{ x: 3, y: 0 },
{ x: 1, y: 3 },
{ x: 3, y: 3 },
{ x: 5, y: 2 }
]
},
{ // page 3
backgroundImage: "eve03.jpg",
menuBackgroundColor: { r: 160, g: 100, b: 0 },
text: [{
html: ' ',
x: 0, y: 0, w: 1, h: 1
},
{
html: ' ',
x: 5, y: 0, w: 1, h: 1
},
{
id: "txt3",
x: 2, y: 1, w: 3, h: 2
},
{
html: '

lägüptän

',
x: 5, y: 2, w: 1, h: 1
}
],
menuTarget: [
{ x: 1, y: 0 },
{ x: 1, y: 2 },
{ x: 5, y: 3 },
{ x: 5, y: 1 }
]
},
{ // page 4
backgroundImage: "eve04.jpg",
menuBackgroundColor: { r: 0, g: 150, b: 150 },
text: [{
id: "txt41",
x: 0, y: 3, w: 2, h: 1
},
{
id: "txt4",
x: 4, y: 2, w: 2, h: 2
},
{
html: '

sofälik

',
x: 3, y: 3, w: 1, h: 1
}
],
menuTarget: [
{ x: 2, y: 0 },
{ x: 1, y: 0 },
{ x: 2, y: 3 },
{ x: 5, y: 0 }
]
}]
});
}, 500);

// For a better World, this script is made from 100% post-consumer Recycled Pixels

Download: http://www.htmldrive.net/items/download/857

Be Sociable, Share!

Leave a comment