Javascript Nested Function Call - javascript

I am trying to develop a javascript library that makes it easier for me to generate DOM Elements and edit their attributes. The problem I am having is that there is so many attributes for some elements that it is making for messy code. For instance I have to programmatically set the color of border, background, shadow, etc. using a method call before generation.
See setBorder Nested in function Div in jLibrary.php
function Div() {
Div.POSITION = {
STATIC : 'static',
ABSOLUTE : 'absolute',
RELATIVE : 'relative',
FIXED : 'fixed'
}
Div.BORDER = {
SOLID : 'solid',
DOTTED : 'dotted'
}
Div.ALIGN = {
LEFT : 0,
CENTER : 1,
RIGHT : 2,
TOP : 0,
MIDDLE : 1,
BOTTOM : 2
}
var ELEMENT;
var CSS;
var horizontalAlign;
var verticalAlign;
var colorQueue;
(function() {
this.div = document.createElement('div');
ELEMENT = this.div;
CSS = this.div.style;
colorQueue = 'rgb(' + new Array(0, 0, 0) + ')';
document.body.appendChild(this.div);
}());
this.setPosition = function(postype) {
if (!horizontalAlign && !verticalAlign) {
CSS.position = postype;
}
}
this.setBounds = function(x, y, width, height) {
CSS.left = x + 'px';
CSS.top = y + 'px';
CSS.width = width + 'px';
CSS.height = height + 'px';
}
this.setColorQueue = function(r, g, b) {
colorQueue = 'rgb(' + new Array(r, g, b) + ')';
alert(colorQueue);
}
this.setBackgroundColorToQueue = function(){
CSS.backgroundColor = colorQueue;
}
this.createShadow = function(x, y, width, height){
CSS.boxShadow = y + 'px ' + x + 'px ' + width + 'px ' + height + 'px ' + colorQueue;
}
this.createBorder = function(width,style){
CSS.border = width + 'px ' + style + ' ' + colorQueue;
/* Theoretical Method.
this.setColor = function(r,g,b){ //This will not work the way I want it...
CSS.border = 'rgb(' + new Array(r, g, b) + ')';
}
*/
}
this.rotateDiv = function(degrees){
CSS.transform = 'rotate(' + degrees + 'deg)';
}
this.horizontalAlign = function(horiz) {
var freeSpaceX = ((window.innerWidth - ELEMENT.offsetWidth) / 2);
var defPadding = '8px';
var defPaddingCenter;
var defPaddingRight;
var defPaddingLeft;
horizontalAlign = true;
if (CSS.position == 'relative' || CSS.position == 'static' || CSS.position == 'absolute') {
CSS.position = 'absolute';
defPaddingCenter = 4;
defPaddingRight = 4;
defPaddingLeft = 8;
} else if (CSS.position == 'fixed') {
defPaddingCenter = 4;
defPaddingRight = 4;
defPaddingLeft = 8;
}
if (horiz == 0) {
if (!verticalAlign) {
CSS.marginTop = defPadding;
}
CSS.marginLeft = defPaddingLeft + 'px';
} else if (horiz == 1) {
if (!verticalAlign) {
CSS.marginTop = defPadding;
}
CSS.marginLeft = freeSpaceX - defPaddingCenter + 'px';
} else if (horiz == 2) {
if (!verticalAlign) {
CSS.marginTop = defPadding;
}
CSS.marginLeft = (freeSpaceX - defPaddingRight) * 2 + 'px';
}
}
this.verticalAlign = function(vertical) {
var freeSpaceY = ((window.innerHeight - ELEMENT.offsetHeight) / 2);
var defPadding = '8px';
var defPaddingTop;
var defPaddingMid;
var defPaddingBot;
verticalAlign = true;
if (CSS.position == 'relative' || CSS.position == 'static') {
CSS.position = 'absolute';
}
defPaddingTop = 8;
defPaddingMid = 8;
defPaddingBot = 8;
if (vertical == 0) {
if (!horizontalAlign) {
CSS.marginLeft = defPadding;
}
CSS.marginTop = defPadding;
} else if (vertical == 1) {
if (!horizontalAlign) {
CSS.marginLeft = defPadding;
}
CSS.marginTop = freeSpaceY - defPaddingMid + 'px';
} else if (vertical == 2) {
if (!horizontalAlign) {
CSS.marginLeft = defPadding;
}
CSS.marginTop = (freeSpaceY * 2) - defPaddingBot + 'px';
}
}
}
setBorder Example in index.php
var div1 = new Div();
div1.setPosition(Div.POSITION.ABSOLUTE);
div1.setBounds(0,700, 200,200);
div1.setColorQueue(0,0,0); //This method must be called every time a different color is needed for a certain attribute.
div1.createBorder(5, Div.BORDER.SOLID); // I really want something like this --> div1.createBorder(5,Div.BORDER.SOLID).setColor(0,0,0);

You can try using the Builder pattern:
function DivBuilder() {
var color;
var border;
var position;
var bounds;
this.DivBuilder = function() {}
this.color = function(c) {
//set the color
this.color = c;
return this;
}
this.border = function(b) {
//set the border
this.border = b;
return this;
}
this.position = function(p) {
//set position
this.position = p;
return this;
}
this.bounds = function(b) {
//set bounds
this.border = b;
return this;
}
this.build = function () {
//build the new Div object with the properties of the builder
var d = new Div(this);
return d;
}
}
and then:
var divb = new DivBuilder();
divb.position().bounds().border().color();
var div = divb.buid();
Main advantage over the telescopic constructor pattern (well, the adaptation of it to javascript) is that you can choose easier which property you want to initialize without having to create many different constructor cases.

If you want to write this.createBorder(...).setColor(...) It means that createBorder should return an object with the setColor method...

Thanks to Sebas I was able to come up with this... Please vote up Sebas if this helped you.
Nested in this.createBorder()
this.createBorder = function(width) {
CSS.border = width + 'px';
function DivBorderBuilder() {
this.setColor = function(r, b, g) {
alert('color');
CSS.borderColor = 'rgb(' + new Array(r, g, b) + ')';
return this;
}
this.setStyle = function(s){
CSS.borderStyle = s;
return this;
}
}return new DivBorderBuilder();
}
Creating Border in index.php
<script>
var div1 = new Div();
div1.setPosition(Div.POSITION.ABSOLUTE);
div1.setBounds(0,700, 200,200);
div1.createBorder(5).setStyle(Div.BORDER.SOLID).setColor(255,0,0);// Works Perfectly Now !
</script>

Related

Random movement of circles created by the script

I have a function that craeates divs with a circle.
Now they are all created and appear at the beginning of the page and go further in order.
Next, I need each circle to appear in a random place. I did this.
Now I need all of them to move randomly across the entire page, I have difficulties with this.
Here is an example of how everything works for one element that is already on the page.
https://jsfiddle.net/quej8wko/
But when I add this code, all my created circles don't move.
I get an error:
"message": "Uncaught TypeError: Cannot set properties of null (setting 'willChange')",
This is probably due to the fact that initially there are no circles on the page. How can I connect the code so that all created circles move?
//creating circles
var widthHeight = 40; // <-- circle width
var margin = 20; // <-- margin - is it necessary ?
var delta = widthHeight + margin;
function createDiv(id, color) {
let div = document.createElement('div');
var currentTop = 0;
var documentHeight = document.documentElement.clientHeight;
var documentWidth = document.documentElement.clientWidth;
div.setAttribute('class', id);
if (color === undefined) {
let colors = ['#35def2', '#35f242', '#b2f235', '#f2ad35', '#f24735', '#3554f2', '#8535f2', '#eb35f2', '#f2359b', '#f23547'];
div.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
}
else {
div.style.backgroundColor = color;
}
div.classList.add("circle");
div.classList.add("animation");
// Get the random positions minus the delta
currentTop = Math.floor(Math.random() * documentHeight) - delta;
currentLeft = Math.floor(Math.random() * documentWidth) - delta;
// Keep the positions between -20px and the current positions
var limitedTop = Math.max(margin * -1, currentTop);
var limitedLeft = Math.max(margin * -1, currentLeft);
div.style.top = limitedTop + "px";
div.style.left = limitedLeft + "px";
document.body.appendChild(div);
}
let i = 0;
const oneSecond = 1000;
setInterval(() => {
i += 1;
createDiv(`circle${i}`)
}, oneSecond);
//move circles
function RandomObjectMover(obj, container) {
this.$object = obj;
this.$container = container;
this.container_is_window = container === window;
this.pixels_per_second = 250;
this.current_position = { x: 0, y: 0 };
this.is_running = false;
}
// Set the speed of movement in Pixels per Second.
RandomObjectMover.prototype.setSpeed = function(pxPerSec) {
this.pixels_per_second = pxPerSec;
}
RandomObjectMover.prototype._getContainerDimensions = function() {
if (this.$container === window) {
return { 'height' : this.$container.innerHeight, 'width' : this.$container.innerWidth };
} else {
return { 'height' : this.$container.clientHeight, 'width' : this.$container.clientWidth };
}
}
RandomObjectMover.prototype._generateNewPosition = function() {
// Get container dimensions minus div size
var containerSize = this._getContainerDimensions();
var availableHeight = containerSize.height - this.$object.clientHeight;
var availableWidth = containerSize.width - this.$object.clientHeight;
// Pick a random place in the space
var y = Math.floor(Math.random() * availableHeight);
var x = Math.floor(Math.random() * availableWidth);
return { x: x, y: y };
}
RandomObjectMover.prototype._calcDelta = function(a, b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
var dist = Math.sqrt( dx*dx + dy*dy );
return dist;
}
RandomObjectMover.prototype._moveOnce = function() {
// Pick a new spot on the page
var next = this._generateNewPosition();
// How far do we have to move?
var delta = this._calcDelta(this.current_position, next);
// Speed of this transition, rounded to 2DP
var speed = Math.round((delta / this.pixels_per_second) * 100) / 100;
//console.log(this.current_position, next, delta, speed);
this.$object.style.transition='transform '+speed+'s linear';
this.$object.style.transform='translate3d('+next.x+'px, '+next.y+'px, 0)';
// Save this new position ready for the next call.
this.current_position = next;
};
RandomObjectMover.prototype.start = function() {
if (this.is_running) {
return;
}
// Make sure our object has the right css set
this.$object.willChange = 'transform';
this.$object.pointerEvents = 'auto';
this.boundEvent = this._moveOnce.bind(this)
// Bind callback to keep things moving
this.$object.addEventListener('transitionend', this.boundEvent);
// Start it moving
this._moveOnce();
this.is_running = true;
}
RandomObjectMover.prototype.stop = function() {
if (!this.is_running) {
return;
}
this.$object.removeEventListener('transitionend', this.boundEvent);
this.is_running = false;
}
// Init it
var x = new RandomObjectMover(document.querySelector(".circle"), window);
// Start it off
x.start();
.circle {
clip-path: circle(50%);
height: 40px;
width: 40px;
margin: 20px;
position: absolute;
}
I have modified the snippet which works as you expected.
There was a mistake where you were initializing and creating the object instance only once and none of the div elements that you created inside the setInterval function never got Instantiated.
I think you are just starting out with JavaScript with this sample project.
Below are few suggestions:
Learn to debug the code. You should be using dev tools by making use of debugger statement where it takes you to the source code to analyze the variable scope and stack during the runtime. console.log also helps in few situations.
I could see a lot of confusing naming convention (You have named the create div parameter as id but creating a div class using that id)
Try using ES6 features (class syntax is really good when writing OOP in JS although it's just a syntactic sugar for prototype)
//creating circles
var widthHeight = 40; // <-- circle width
var margin = 20; // <-- margin - is it necessary ?
var delta = widthHeight + margin;
function createAndInitializeDivObject(id, color) {
let div = document.createElement('div');
var currentTop = 0;
var documentHeight = document.documentElement.clientHeight;
var documentWidth = document.documentElement.clientWidth;
div.setAttribute('class', id);
if (color === undefined) {
let colors = ['#35def2', '#35f242', '#b2f235', '#f2ad35', '#f24735', '#3554f2', '#8535f2', '#eb35f2', '#f2359b', '#f23547'];
div.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
}
else {
div.style.backgroundColor = color;
}
div.classList.add("circle");
div.classList.add("animation");
// Get the random positions minus the delta
currentTop = Math.floor(Math.random() * documentHeight) - delta;
currentLeft = Math.floor(Math.random() * documentWidth) - delta;
// Keep the positions between -20px and the current positions
var limitedTop = Math.max(margin * -1, currentTop);
var limitedLeft = Math.max(margin * -1, currentLeft);
div.style.top = limitedTop + "px";
div.style.left = limitedLeft + "px";
document.body.appendChild(div);
var x = new RandomObjectMover(document.querySelector(`.${id}`), window);
x.start();
}
let i = 0;
const oneSecond = 1000;
setInterval(() => {
i += 1;
createAndInitializeDivObject(`circle${i}`)
}, oneSecond);
//move circles
function RandomObjectMover(obj, container) {
this.$object = obj;
this.$container = container;
this.container_is_window = container === window;
this.pixels_per_second = 250;
this.current_position = { x: 0, y: 0 };
this.is_running = false;
}
// Set the speed of movement in Pixels per Second.
RandomObjectMover.prototype.setSpeed = function(pxPerSec) {
this.pixels_per_second = pxPerSec;
}
RandomObjectMover.prototype._getContainerDimensions = function() {
if (this.$container === window) {
return { 'height' : this.$container.innerHeight, 'width' : this.$container.innerWidth };
} else {
return { 'height' : this.$container.clientHeight, 'width' : this.$container.clientWidth };
}
}
RandomObjectMover.prototype._generateNewPosition = function() {
// Get container dimensions minus div size
var containerSize = this._getContainerDimensions();
var availableHeight = containerSize.height - this.$object.clientHeight;
var availableWidth = containerSize.width - this.$object.clientHeight;
// Pick a random place in the space
var y = Math.floor(Math.random() * availableHeight);
var x = Math.floor(Math.random() * availableWidth);
return { x: x, y: y };
}
RandomObjectMover.prototype._calcDelta = function(a, b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
var dist = Math.sqrt( dx*dx + dy*dy );
return dist;
}
RandomObjectMover.prototype._moveOnce = function() {
// Pick a new spot on the page
var next = this._generateNewPosition();
// How far do we have to move?
var delta = this._calcDelta(this.current_position, next);
// Speed of this transition, rounded to 2DP
var speed = Math.round((delta / this.pixels_per_second) * 100) / 100;
//console.log(this.current_position, next, delta, speed);
this.$object.style.transition='transform '+speed+'s linear';
this.$object.style.transform='translate3d('+next.x+'px, '+next.y+'px, 0)';
// Save this new position ready for the next call.
this.current_position = next;
};
RandomObjectMover.prototype.start = function() {
if (this.is_running) {
return;
}
// Make sure our object has the right css set
this.$object.willChange = 'transform';
this.$object.pointerEvents = 'auto';
this.boundEvent = this._moveOnce.bind(this)
// Bind callback to keep things moving
this.$object.addEventListener('transitionend', this.boundEvent);
// Start it moving
this._moveOnce();
this.is_running = true;
}
RandomObjectMover.prototype.stop = function() {
if (!this.is_running) {
return;
}
this.$object.removeEventListener('transitionend', this.boundEvent);
this.is_running = false;
}
// Init it
var x = new RandomObjectMover(document.querySelector(".circle"), window);
// Start it off
x.start();
.circle {
width: 35px;
height: 35px;
border-radius: 35px;
background-color: #ffffff;
border: 3px solid purple;
position: absolute;
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="circle"></div>
<script src="app.js"></script>
</body>
</html>

How to collide using OOP JavaScript?

I am making a game(shooting game) using OOP javascript for my project. I already moved(player) and make the enemy disappear at the edge of the container. Now, I want to collide with the shooter(player) and enemy and display the message "Game Over". Here is my code of enemy.js and shooter.js. Also, my container.js.
container.js
class Container{
constructor(){
this.containerElement = document.getElementsByClassName("container")[0];
}
initialization(){
this.shooterElement = document.getElementsByClassName("shooter")[0];
let containerElement = document.getElementsByClassName("container")[0];
this.backgroundElement = document.getElementsByClassName("background")[0];
this.background = new Background(this.backgroundElement);
this.shooter = new Shooter(this.shooterElement);
document.addEventListener('keydown', (e)=>this.shooter.buttonGotPressed(e));
let enemyElement = document.getElementsByClassName("enemy")[0];
this.enemies = [];
setInterval(function(){
var top = Math.floor(Math.random() * 50) + 1;
var left = Math.floor(Math.random() * 550) + 1;
this.enemy = new Enemy({parentElement: containerElement, leftPosition: left, topPosition: top});
},400)
this.enemies.push(this.enemy);
}
}
let container = new Container();
container.initialization();
enemy.js
class Enemy{
constructor({parentElement,leftPosition, topPosition }){
let enemyElement = document.createElement("div");
this.enemyElement = enemyElement;
this.leftPosition = leftPosition;
this.topPosition = topPosition;
this.containerHeight = 600;
this.y = 15;
this.height = 40;
this.width = 50;
this.enemyElement.style.left = this.leftPosition + 'px';
this.enemyElement.style.top= this.topPosition + 'px';
this.enemyElement.style.height = this.height + 'px';
this.enemyElement.style.width = this.width + 'px';
this.enemyElement.style.position = "absolute";
this.enemyElement.style.background="url(images/enemy3.png)";
console.log(enemyElement)
parentElement.appendChild(this.enemyElement);
this.containerCollision = this.containerCollision.bind(this);
setInterval(this.containerCollision, 100);
}
containerCollision(){
if(this.topPosition >= this.containerHeight - this.width ){
this.enemyElement.style.display="none";
}
this.topPosition = this.topPosition + this.y;
this.enemyElement.style.top = this.topPosition + 'px';
}
}
shooter.js (this is the player)
class Shooter {
constructor(shooterElement){
this.shooterElement = shooterElement;
this.shooterleftPosition = 300;
this.shootertopPosition = 555;
this.containerWidth = 600;
this.width = 30;
this.height = 40;
this.x = 5;
this.y = 1;
this.shooterElement.style.left = this.shooterleftPosition + 'px';
this.shooterElement.style.top = this.shootertopPosition + 'px';
this.buttonGotPressed = this.buttonGotPressed.bind(this);
}
buttonGotPressed(e){
console.log(e);
if(e.key == "ArrowLeft"){
console.log(e.key);
if(this.shooterleftPosition <= 0){
this.shooterleftPosition = 0;
}
else
{
this.shooterleftPosition = this.shooterleftPosition - this.x;
}
console.log(this.shooterleftPosition)
this.shooterElement.style.left = this.shooterleftPosition +'px';
}
if(e.key == "ArrowRight"){
this.shooterleftPosition = this.shooterleftPosition + this.x;
this.shooterElement.style.left = this.shooterleftPosition +'px';
if(this.shooterleftPosition >= this.containerWidth - this.width){
this.shooterleftPosition = this.containerWidth - this.width;
this.shooterElement.style.left = this.leftPosition + 'px';
}
}
}
}
Now, How do I detect and collide shooter(player) and enemy and display the message/alert "Game Over". If the enemy touches the shooter(player). Here is pic too.
How do i know enemy touched the player and display game over in this pic
What I tried to detect the collision of player and enemy
collidingShooter(){
if (this.enemies.push(this.enemy)>1)
{
(
([this.enemies][this.enemy].top <= this.shootertopPosition + 50) &&
([this.enemies][this.enemy].top >= this.shootertopPosition) &&
([this.enemies][this.enemy].left >= this.shooterleftPosition) &&
([this.enemies][this.enemy].left <= this.shooterleftPosition+ 50)
)
console.log("hitttt");
this.enemies.splice(this.enemy,1);
// this.shooterElement.splice(1);
}
}
I believe that you messed something up here
First of all you use array in the wrong way:
[this.enemies][this.enemy].top
What it does:
Creates new array with one element (which is this.enemies array), now it converts this.enemy to a string = 'object Object' and tries to find a key in this new array, which propably returns undefined and now it tries to get top of undefined.
What you probably wanted to do is:
this.enemies[this.enemies.indexOf(this.enemy)].top
But even though it has no oop sense.
What I would do:
function checkCollision() {
for (let i = 0; i < this.enemies.length; i++) {
if (areColliding(this.shooter, this.enemies[i])) {
console.log('hit')
}
}
}
function areColliding(o1, o2) {
if (o1.top <= o2.top + o2.height &&
o1.top >= o2.top &&
o1.left <= o2.left + o2.width &&
o1.left >= o2.left) {
return true
}
return false
}
There are better collision algorithms than aabb and even if you want to do this in this way, your game can get very slow if you have thousands of enemies. There is algorithm to split game world in to smaller rectangles and check for collision inside them.

Transforming img - white dots appear on chronium

I am trying to get 3d transform effect of the bacground image on mouse move.
I have checked f.e. jquery.plate tilt.js and many others plugins, BUT, each of them has problem on chronium browsers like Chrome or Opera (it works fine even on IE11 -.-)
See the attachment and please adwise what is that and if it is fixable? The "dots" appear on mouse move (when background moves) randomly but in line within image.
(function($) {
'use strict';
var namespace = 'jquery-plate';
function Plate($element, options) {
this.config(options);
this.$container = $element;
if (this.options.element) {
if (typeof this.options.element === 'string') {
this.$element = this.$container.find(this.options.element);
} else {
this.$element = $(this.options.element);
}
} else {
this.$element = $element;
}
this.originalTransform = this.$element.css('transform');
this.$container
.on('mouseenter.' + namespace, this.onMouseEnter.bind(this))
.on('mouseleave.' + namespace, this.onMouseLeave.bind(this))
.on('mousemove.' + namespace, this.onMouseMove.bind(this));
}
Plate.prototype.config = function(options) {
this.options = $.extend({
inverse: false,
perspective: 500,
maxRotation: 10,
animationDuration: 200
}, this.options, options);
};
Plate.prototype.destroy = function() {
this.$element.css('transform', this.originalTransform);
this.$container.off('.' + namespace);
};
Plate.prototype.update = function(offsetX, offsetY, duration) {
var rotateX;
var rotateY;
if (offsetX || offsetX === 0) {
var height = this.$container.outerHeight();
var py = (offsetY - height / 2) / (height / 2);
rotateX = this.round(this.options.maxRotation * -py);
} else {
rotateY = 0;
}
if (offsetY || offsetY === 0) {
var width = this.$container.outerWidth();
var px = (offsetX - width / 2) / (width / 2);
rotateY = this.round(this.options.maxRotation * px);
} else {
rotateX = 0;
}
if (this.options.inverse) {
rotateX *= -1;
rotateY *= -1;
}
if (duration) {
this.animate(rotateX, rotateY, duration);
} else if (this.animation && this.animation.remaining) {
this.animation.targetX = rotateX;
this.animation.targetY = rotateY;
} else {
this.transform(rotateX, rotateY);
}
};
Plate.prototype.reset = function(duration) {
this.update(null, null, duration);
};
Plate.prototype.transform = function(rotateX, rotateY) {
this.currentX = rotateX;
this.currentY = rotateY;
this.$element.css('transform',
(this.originalTransform && this.originalTransform !== 'none' ? this.originalTransform + ' ' : '') +
'perspective(' + this.options.perspective + 'px) ' +
'rotateX(' + rotateX + 'deg) rotateY(' + rotateY + 'deg)'
);
};
Plate.prototype.animate = function(rotateX, rotateY, duration) {
if (duration) {
this.animation = this.animation || {};
var remaining = this.animation.remaining;
this.animation.time = performance.now();
this.animation.remaining = duration || null;
this.animation.targetX = rotateX;
this.animation.targetY = rotateY;
if (!remaining) {
requestAnimationFrame(this.onAnimationFrame.bind(this));
}
} else {
this.transform(rotateX, rotateY);
}
};
Plate.prototype.round = function(number) {
return Math.round(number * 1000) / 1000;
};
Plate.prototype.offsetCoords = function(event) {
var offset = this.$container.offset();
return {
x: event.pageX - offset.left,
y: event.pageY - offset.top
};
};
Plate.prototype.onAnimationFrame = function(timestamp) {
this.animation = this.animation || {};
var delta = timestamp - (this.animation.time || 0);
this.animation.time = timestamp;
var duration = this.animation.remaining || 0;
var percent = Math.min(delta / duration, 1);
var currentX = this.currentX || 0;
var currentY = this.currentY || 0;
var targetX = this.animation.targetX || 0;
var targetY = this.animation.targetY || 0;
var rotateX = this.round(currentX + (targetX - currentX) * percent);
var rotateY = this.round(currentY + (targetY - currentY) * percent);
this.transform(rotateX, rotateY);
var remaining = duration - delta;
this.animation.remaining = remaining > 0 ? remaining : null;
if (remaining > 0) {
requestAnimationFrame(this.onAnimationFrame.bind(this));
}
};
Plate.prototype.onMouseEnter = function(event) {
var offset = this.offsetCoords(event);
this.update(offset.x, offset.y, this.options.animationDuration);
};
Plate.prototype.onMouseLeave = function(event) {
this.reset(this.options.animationDuration);
};
Plate.prototype.onMouseMove = function(event) {
var offset = this.offsetCoords(event);
this.update(offset.x, offset.y);
};
$.fn.plate = function(options) {
return this.each(function() {
var $element = $(this);
var plate = $element.data(namespace);
if (options === 'remove') {
plate.destroy();
$element.data(namespace, null);
} else {
if (!plate) {
plate = new Plate($element, options);
$element.data(namespace, plate);
plate.reset();
} else {
plate.config(options);
}
}
});
};
})(jQuery);
$('#ab12cd').plate()
<div id="ab12cd" styles="width:100%;height:100%">
<img src="http://eskipaper.com/images/dark-background-8.jpg" />
</div>
<script
src="https://code.jquery.com/jquery-3.2.1.min.js"
integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
crossorigin="anonymous"></script>
// please open in new window, most visible effect you cen see if you move mouse bottom left/right

Cloudzoom and woocommerce attributes

I cannot get cloudzoom to work with my woocommerce site, every time I choose an attribute ie size the main image disappears, it is like cloudzoom is trying to force an attribute image. I am absolutely pants at javascript and looking through the file I cannot see where I need to edit or delete the code. Any help would be greatly appreciated, I don't need the atribute image function to work at all so just stripping out the code would suit me. Here is the code...
(function ($) {
$(document).ready(function () {
$('.cloud-zoom, .cloud-zoom-gallery').CloudZoom();
});
function format(str) {
for (var i = 1; i < arguments.length; i++) {
str = str.replace('%' + (i - 1), arguments[i]);
}
return str;
}
function CloudZoom(jWin, opts) {
var sImg = $('img', jWin);
var img1;
var img2;
var zoomDiv = null;
var $mouseTrap = null;
var lens = null;
var $tint = null;
var softFocus = null;
var $ie6Fix = null;
var zoomImage;
var controlTimer = 0;
var cw, ch;
var destU = 0;
var destV = 0;
var currV = 0;
var currU = 0;
var filesLoaded = 0;
var mx,
my;
var ctx = this, zw;
// Display an image loading message. This message gets deleted when the images have loaded and the zoom init function is called.
// We add a small delay before the message is displayed to avoid the message flicking on then off again virtually immediately if the
// images load really fast, e.g. from the cache.
//var ctx = this;
setTimeout(function () {
// <img src="/images/loading.gif"/>
if ($mouseTrap === null) {
var w = jWin.width();
jWin.parent().append(format('<div style="width:%0px;position:absolute;top:75%;left:%1px;text-align:center" class="cloud-zoom-loading" >Loading...</div>', w / 3, (w / 2) - (w / 6))).find(':last').css('opacity', 0.5);
}
}, 200);
var ie6FixRemove = function () {
if ($ie6Fix !== null) {
$ie6Fix.remove();
$ie6Fix = null;
}
};
// Removes cursor, tint layer, blur layer etc.
this.removeBits = function () {
//$mouseTrap.unbind();
if (lens) {
lens.remove();
lens = null;
}
if ($tint) {
$tint.remove();
$tint = null;
}
if (softFocus) {
softFocus.remove();
softFocus = null;
}
ie6FixRemove();
$('.cloud-zoom-loading', jWin.parent()).remove();
};
this.destroy = function () {
jWin.data('zoom', null);
if ($mouseTrap) {
$mouseTrap.unbind();
$mouseTrap.remove();
$mouseTrap = null;
}
if (zoomDiv) {
zoomDiv.remove();
zoomDiv = null;
}
//ie6FixRemove();
this.removeBits();
// DON'T FORGET TO REMOVE JQUERY 'DATA' VALUES
};
// This is called when the zoom window has faded out so it can be removed.
this.fadedOut = function () {
if (zoomDiv) {
zoomDiv.remove();
zoomDiv = null;
}
this.removeBits();
//ie6FixRemove();
};
this.controlLoop = function () {
if (lens) {
var x = (mx - sImg.offset().left - (cw * 0.5)) >> 0;
var y = (my - sImg.offset().top - (ch * 0.5)) >> 0;
if (x < 0) {
x = 0;
}
else if (x > (sImg.outerWidth() - cw)) {
x = (sImg.outerWidth() - cw);
}
if (y < 0) {
y = 0;
}
else if (y > (sImg.outerHeight() - ch)) {
y = (sImg.outerHeight() - ch);
}
lens.css({
left: x,
top: y
});
lens.css('background-position', (-x) + 'px ' + (-y) + 'px');
destU = (((x) / sImg.outerWidth()) * zoomImage.width) >> 0;
destV = (((y) / sImg.outerHeight()) * zoomImage.height) >> 0;
currU += (destU - currU) / opts.smoothMove;
currV += (destV - currV) / opts.smoothMove;
zoomDiv.css('background-position', (-(currU >> 0) + 'px ') + (-(currV >> 0) + 'px'));
}
controlTimer = setTimeout(function () {
ctx.controlLoop();
}, 30);
};
this.init2 = function (img, id) {
filesLoaded++;
//console.log(img.src + ' ' + id + ' ' + img.width);
if (id === 1) {
zoomImage = img;
}
//this.images[id] = img;
if (filesLoaded === 2) {
this.init();
}
};
/* Init function start. */
this.init = function () {
// Remove loading message (if present);
$('.cloud-zoom-loading', jWin.parent()).remove();
/* Add a box (mouseTrap) over the small image to trap mouse events.
It has priority over zoom window to avoid issues with inner zoom.
We need the dummy background image as IE does not trap mouse events on
transparent parts of a div.
*/
$mouseTrap = jWin.parent().append(format("<div class='mousetrap' style='background-image:url(\".\");z-index:3;position:absolute;width:%0px;height:%1px;left:%2px;top:%3px;\'></div>", sImg.outerWidth(), sImg.outerHeight(), 0, 0)).find(':last');
//////////////////////////////////////////////////////////////////////
/* Do as little as possible in mousemove event to prevent slowdown. */
$mouseTrap.bind('mousemove', this, function (event) {
// Just update the mouse position
mx = event.pageX;
my = event.pageY;
});
//////////////////////////////////////////////////////////////////////
$mouseTrap.bind('mouseleave', this, function (event) {
clearTimeout(controlTimer);
//event.data.removeBits();
if(lens) { lens.fadeOut(299); }
if($tint) { $tint.fadeOut(299); }
if(softFocus) { softFocus.fadeOut(299); }
zoomDiv.fadeOut(300, function () {
ctx.fadedOut();
});
return false;
});
//////////////////////////////////////////////////////////////////////
$mouseTrap.bind('mouseenter', this, function (event) {
mx = event.pageX;
my = event.pageY;
zw = event.data;
if (zoomDiv) {
zoomDiv.stop(true, false);
zoomDiv.remove();
}
var xPos = opts.adjustX,
yPos = opts.adjustY;
var siw = sImg.outerWidth();
var sih = sImg.outerHeight();
var w = opts.zoomWidth;
var h = opts.zoomHeight;
if (opts.zoomWidth == 'auto') {
w = siw;
}
if (opts.zoomHeight == 'auto') {
h = sih;
}
//$('#info').text( xPos + ' ' + yPos + ' ' + siw + ' ' + sih );
var appendTo = jWin.parent(); // attach to the wrapper
switch (opts.position) {
case 'top':
yPos -= h; // + opts.adjustY;
break;
case 'right':
xPos += siw; // + opts.adjustX;
break;
case 'bottom':
yPos += sih; // + opts.adjustY;
break;
case 'left':
xPos -= w; // + opts.adjustX;
break;
case 'inside':
w = siw;
h = sih;
break;
// All other values, try and find an id in the dom to attach to.
default:
appendTo = $('#' + opts.position);
// If dom element doesn't exit, just use 'right' position as default.
if (!appendTo.length) {
appendTo = jWin;
xPos += siw; //+ opts.adjustX;
yPos += sih; // + opts.adjustY;
} else {
w = appendTo.innerWidth();
h = appendTo.innerHeight();
}
}
zoomDiv = appendTo.append(format('<div id="cloud-zoom-big" class="cloud-zoom-big" style="display:none;position:absolute;left:%0px;top:%1px;width:%2px;height:%3px;background-image:url(\'%4\');z-index:2;"></div>', xPos, yPos, w, h, zoomImage.src)).find(':last');
// Add the title from title tag.
if (sImg.attr('title') && opts.showTitle) {
zoomDiv.append(format('<div class="cloud-zoom-title">%0</div>', sImg.attr('title'))).find(':last').css('opacity', opts.titleOpacity);
}
// Fix ie6 select elements wrong z-index bug. Placing an iFrame over the select element solves the issue...
if ($.browser.msie && $.browser.version < 7) {
$ie6Fix = $('<iframe frameborder="0" src="#"></iframe>').css({
position: "absolute",
left: xPos,
top: yPos,
zIndex: 99,
width: w,
height: h
}).insertBefore(zoomDiv);
}
zoomDiv.fadeIn(500);
if (lens) {
lens.remove();
lens = null;
} /* Work out size of cursor */
cw = (sImg.outerWidth() / zoomImage.width) * zoomDiv.width();
ch = (sImg.outerHeight() / zoomImage.height) * zoomDiv.height();
// Attach mouse, initially invisible to prevent first frame glitch
lens = jWin.append(format("<div class = 'cloud-zoom-lens' style='display:none;z-index:1;position:absolute;width:%0px;height:%1px;opacity:0.4'></div>", cw, ch)).find(':last');
$mouseTrap.css('cursor', lens.css('cursor'));
var noTrans = false;
// Init tint layer if needed. (Not relevant if using inside mode)
if (opts.tint) {
/* lens.css('background', 'url("' + sImg.attr('src') + '")'); */
$tint = jWin.append(format('<div style="display:none;position:absolute; left:0px; top:0px; width:%0px; height:%1px; background-color:%2;" />', sImg.outerWidth(), sImg.outerHeight(), opts.tint)).find(':last');
$tint.css('opacity', opts.tintOpacity);
noTrans = true;
$tint.fadeIn(500);
}
if (opts.softFocus) {
lens.css('background', 'url("' + sImg.attr('src') + '")');
softFocus = jWin.append(format('<div style="position:absolute;display:none;top:2px; left:2px; width:%0px; height:%1px;" />', sImg.outerWidth() - 2, sImg.outerHeight() - 2, opts.tint)).find(':last');
softFocus.css('background', 'url("' + sImg.attr('src') + '")');
softFocus.css('opacity', 0.5);
noTrans = true;
softFocus.fadeIn(500);
}
if (!noTrans) {
lens.css('opacity', opts.lensOpacity);
}
if ( opts.position !== 'inside' ) { lens.fadeIn(500); }
// Start processing.
zw.controlLoop();
return; // Don't return false here otherwise opera will not detect change of the mouse pointer type.
});
};
img1 = new Image();
$(img1).load(function () {
ctx.init2(this, 0);
});
img1.src = sImg.attr('src');
img2 = new Image();
$(img2).load(function () {
ctx.init2(this, 1);
});
img2.src = jWin.attr('href');
}
$.fn.CloudZoom = function (options) {
// IE6 background image flicker fix
try {
document.execCommand("BackgroundImageCache", false, true);
} catch (e) {}
this.each(function () {
var relOpts, opts;
// Hmm...eval...slap on wrist.
eval('var a = {' + $(this).attr('rel') + '}');
relOpts = a;
if ($(this).is('.cloud-zoom')) {
$(this).css({
'position': 'relative',
'display': 'block'
});
$('img', $(this)).css({
'display': 'block'
});
// Wrap an outer div around the link so we can attach things without them becoming part of the link.
// But not if wrap already exists.
if ($(this).parent().attr('id') != 'wrap') {
$(this).wrap('<div id="wrap" style="top:0px;z-index:4;position:relative;"></div>');
}
opts = $.extend({}, $.fn.CloudZoom.defaults, options);
opts = $.extend({}, opts, relOpts);
$(this).data('zoom', new CloudZoom($(this), opts));
} else if ($(this).is('.cloud-zoom-gallery')) {
opts = $.extend({}, relOpts, options);
$(this).data('relOpts', opts);
$(this).bind('click', $(this), function (event) {
var data = event.data.data('relOpts');
// Destroy the previous zoom
$('#' + data.useZoom).data('zoom').destroy();
// Change the biglink to point to the new big image.
$('#' + data.useZoom).attr('href', event.data.attr('href'));
// Change the small image to point to the new small image.
$('#' + data.useZoom + ' img').attr('src', event.data.data('relOpts').smallImage);
// Init a new zoom with the new images.
$('#zoom-cb').attr('href', event.data.attr('href'));
$('#' + event.data.data('relOpts').useZoom).CloudZoom();
return false;
});
}
});
return this;
};
$.fn.CloudZoom.defaults = {
zoomWidth: 'auto',
zoomHeight: 'auto',
position: 'right',
tint: false,
tintOpacity: 0.5,
lensOpacity: 0.5,
softFocus: false,
smoothMove: 3,
showTitle: false,
titleOpacity: 0.5,
adjustX: 0,
adjustY: 0
};
})(jQuery);

How to change arrow length for arrow overlay

The Issue
I am using the following example code to draw arrows on google map.
Here is the main overlay function that creates the svg files for the arrow.
// A small directable Arrow overlay for GMaps V3
// Bill Chadwick Feb 2012 after my previous V2 API version
// Free for any use as far as I am concerned
// Some public domain code VML/SVG utility code of Ben Appleton's is reused at the end of this file
var arrowOverlayMarkerCounter; //unique id counter for SVG arrow head markers
function ArrowOverlay(map, location, rotation, color, opacity, tooltip) {
this.map_ = map;
this.location_ = location;
this.rotation_ = rotation || 0.0;
var r = this.rotation_ + 90; //compass to math
this.dx_ = 20 * Math.cos(r * Math.PI / 180); //other end of arrow line to point
this.dy_ = 20 * Math.sin(r * Math.PI / 180);
this.color_ = color || "#0000FF";
this.opacity_ = opacity || 0.7;
this.tooltip_ = tooltip || "";
this.div_ = null;
this.setMap(map);
this.handle_ = null;//click event handler handle
if (arrowOverlayMarkerCounter == null)
arrowOverlayMarkerCounter = 0;
else
arrowOverlayMarkerCounter += 1;
this.svgId_ = "ArrowOverlay" + arrowOverlayMarkerCounter.toString();
}
ArrowOverlay.prototype = new google.maps.OverlayView();
ArrowOverlay.prototype.onAdd = function() {
// Create the DIV and set some basic attributes.
var div = document.createElement('DIV');
div.title = this.tooltip_;
div.style.cursor = "help";
var obj = this;
this.handle_ = google.maps.event.addDomListener(div, 'click', function() { google.maps.event.trigger(obj, "click") });
//set up arrow invariants
if (supportsVML()) {
var l = createVmlElement('v:line', div);
l.strokeweight = "3px";
l.strokecolor = this.color_;
l.style.position = 'absolute';
var s = createVmlElement("v:stroke", l);
s.opacity = this.opacity_;
s.startarrow = "classic"; // or "block", "open" etc see VML spec
this.vmlLine_ = l;
}
else {
// make a 40x40 pixel space centered on the arrow
var svgNS = "http://www.w3.org/2000/svg";
var svgRoot = document.createElementNS(svgNS, "svg");
svgRoot.setAttribute("width", 40);
svgRoot.setAttribute("height", 40);
svgRoot.setAttribute("stroke", this.color_);
svgRoot.setAttribute("fill", this.color_);
svgRoot.setAttribute("stroke-opacity", this.opacity_);
svgRoot.setAttribute("fill-opacity", this.opacity_);
div.appendChild(svgRoot);
var svgNode = document.createElementNS(svgNS, "line");
svgNode.setAttribute("stroke-width", 3);
svgNode.setAttribute("x1", 20);
svgNode.setAttribute("y1", 20);
svgNode.setAttribute("x2", 20 + this.dx_);
svgNode.setAttribute("y2", 20 + this.dy_);
//make a solid arrow head, can't share these, as in SVG1.1 they can't get color from the referencing object, only their parent
//a bit more involved than the VML
if (this.rotation_ >= 0) {
var svgM = document.createElementNS(svgNS, "marker");
svgM.id = this.svgId_;
svgM.setAttribute("viewBox", "0 0 10 10");
svgM.setAttribute("refX", 0);
svgM.setAttribute("refY", 5);
svgM.setAttribute("markerWidth", 4);
svgM.setAttribute("markerHeight", 3);
svgM.setAttribute("orient", "auto");
var svgPath = document.createElementNS(svgNS, "path"); //could share this with 'def' and 'use' but hardly worth it
svgPath.setAttribute("d", "M 10 0 L 0 5 L 10 10 z");
svgM.appendChild(svgPath);
svgRoot.appendChild(svgM);
svgNode.setAttribute("marker-start", "url(#" + this.svgId_ + ")");
}
svgRoot.appendChild(svgNode);
this.svgRoot_ = svgRoot;
this.svgNode_ = svgNode;
}
// Set the overlay's div_ property to this DIV
this.div_ = div;
var panes = this.getPanes();
panes.overlayImage.appendChild(this.div_);
}
ArrowOverlay.prototype.draw = function() {
var overlayProjection = this.getProjection();
var p = overlayProjection.fromLatLngToDivPixel(this.location_);
var div = this.div_;
if (!div)
return;
if (!div.style)
return;
// Calculate the DIV coordinates of the ref point of our arrow
var x2 = p.x + this.dx_;
var y2 = p.y + this.dy_;
if (supportsVML()) {
this.vmlLine_.from = p.x + "px, " + p.y + "px";
this.vmlLine_.to = x2 + "px, " + y2 + "px";
}
else {
this.svgRoot_.setAttribute("style", "position:absolute; top:" + (p.y - 20) + "px; left:" + (p.x - 20) + "px");
}
}
ArrowOverlay.prototype.onRemove = function() {
if (this.handle_ != null) {
google.maps.eventclear.removeListener(this.handle_);
}
this.div_.parentNode.removeChild(this.div_);
}
ArrowOverlay.prototype.setVisible = function(v) {
if (v)
this.show();
else
this.hide();
}
ArrowOverlay.prototype.getVisible = function(v) {
if (this.div_) {
return (this.div_.style.display == "");
}
return false;
}
ArrowOverlay.prototype.hide = function() {
if (this.div_) {
this.div_.style.display = "none";
}
}
ArrowOverlay.prototype.show = function() {
if (this.div_) {
this.div_.style.display = "";
}
}
ArrowOverlay.prototype.setPosition = function(l) {
this.location_ = l;
this.draw();
}
ArrowOverlay.prototype.getPosition = function() {
return this.location_;
}
ArrowOverlay.prototype.setHeading = function(h) {
this.rotation_ = h || 0.0;
var r = this.rotation_ + 90; //compass to math
this.dx_ = 20 * Math.cos(r * Math.PI / 180); //other end of arrow line to point
this.dy_ = 20 * Math.sin(r * Math.PI / 180);
if (!supportsVML()) {
this.svgNode_.setAttribute("x2", 20 + this.dx_);
this.svgNode_.setAttribute("y2", 20 + this.dy_);
}
this.draw();
}
ArrowOverlay.prototype.getHeading = function() {
return this.rotation_;
}
ArrowOverlay.prototype.setTooltip = function(t) {
this.tooltip_ = t;
}
ArrowOverlay.prototype.getTooltip = function() {
return this.tooltip_;
}
ArrowOverlay.prototype.toggle = function() {
if (this.div_) {
if (this.div_.style.visibility == "hidden") {
this.show();
} else {
this.hide();
}
}
}
ArrowOverlay.prototype.fromDivPixelToLatLng = function(x, y) {
var overlayProjection = this.getProjection();
return overlayProjection.fromDivPixelToLatLng(new google.maps.Point(x, y));
}
ArrowOverlay.prototype.fromLatLngToContainerPixel = function(p) {
var overlayProjection = this.getProjection();
return overlayProjection.fromLatLngToContainerPixel(p);
}
// SVG utils from here http://appleton-static.appspot.com/static/simple_poly.js
// by Ben Appleton of Google
var SVG_NAMESPACE = 'http://www.w3.org/2000/svg';
function supportsSVG() {
return document.implementation.hasFeature(
'http://www.w3.org/TR/SVG11/feature#Shape',
'1.1');
}
// VML utils from here http://appleton-static.appspot.com/static/simple_poly.js
// by Ben Appleton of Google
var VML_NAMESPACE = 'urn:schemas-microsoft-com:vml';
function createVmlElement(tagName, parent) {
var element = document.createElement(tagName);
parent.appendChild(element);
element.style['behavior'] = 'url(#default#VML)';
return element;
}
function supportsVML() {
if (supportsVML.result_ == null) {
if (!maybeCreateVmlNamespace()) {
return supportsVML.result_ = false;
}
// Create some VML. Its 'adj' property will be an object only when VML
// is enabled.
var div = document.createElement('DIV');
document.body.appendChild(div);
div.innerHtml = '<v:shape id="vml_flag1" adj="1" />';
var child = div.firstChild;
if (child) child.style['behavior'] = 'url(#default#VML)';
supportsVML.result_ = !child || (typeof child['adj'] == 'object');
div.parentNode.removeChild(div);
}
return supportsVML.result_;
}
function maybeCreateVmlNamespace() {
var hasVmlNamespace = false;
if (document.namespaces) {
for (var x = 0; x < document.namespaces.length; x++) {
var ns = document.namespaces(x);
if (ns.name == 'v') {
if (ns.urn == VML_NAMESPACE) {
hasVmlNamespace = true;
} else {
throw new Error('document namespace v: is required for VML ' +
'but has been reserved for ' + ns.urn);
}
}
}
if (!hasVmlNamespace) {
// Import namespace
hasVmlNamespace = true;
document.namespaces.add('v', VML_NAMESPACE);
}
}
return hasVmlNamespace;
}
Question
I can not figure out how to change the length of those arrow? Can I somehow add a length parameter to the function ArrowOverlay?
I would do something like this (scale also works with x, y):
<svg>
<g id="idG" transform="scale(1, 1)">
..your arrow
</g>
</svg>
document.getElementById("idG").setAttribute("transform", "scale(" + horizontalScale + "," + verticalScale + ")");
Example: http://k8.no-ip.org/stackoverflow/13540341.htm

Categories