I have this jQuery plugin here:
$.fn.jqrotate = function(degrees, options)
{
var options = $.extend({
animate : false // not yet implemented
}, options);
return this.each(function()
{
var $this = $(this);
var oObj = $this[0];
var deg2radians = Math.PI * 2 / 360;
var rad = degrees * deg2radians;
var costheta = Math.cos(rad);
var sintheta = Math.sin(rad);
a = parseFloat(costheta).toFixed(8);
b = parseFloat(-sintheta).toFixed(8);
c = parseFloat(sintheta).toFixed(8);
d = parseFloat(costheta).toFixed(8);
$this.css( { '-ms-filter' : 'progid:DXImageTransform.Microsoft.Matrix(M11=' + a + ', M12=' + b + ', M21=' + c + ', M22=' + d + ',sizingMethod=\'auto expand\')',
'filter' : 'progid:DXImageTransform.Microsoft.Matrix(M11=' + a + ', M12=' + b + ', M21=' + c + ', M22=' + d + ',sizingMethod=\'auto expand\')',
'-moz-transform' : "matrix(" + a + ", " + c + ", " + b + ", " + d + ", 0, 0)",
'-webkit-transform' : "matrix(" + a + ", " + c + ", " + b + ", " + d + ", 0, 0)",
'-o-transform' : "matrix(" + a + ", " + c + ", " + b + ", " + d + ", 0, 0)"
});
});
};
That I use like so:
$(document).ready(function(){
var degree = 0;
$(".big-ball").click(function(){
degree += 90;
$(this).jqrotate(degree);
});
});
That does the job for rotating it very nice, but I'd like to animate the rotation process, what can be done to make it happen with the given plugin? (fyi: changing animate: false to true doesn't enable it :) )
Thank you.
Related
I am creating an interactive map that allows the user to select year from timeline and filter events, this is done via XML HttpRequest that redraws the SVG everytime.
The SVG code for the map, including the JavaScript functions to zoom and the tooltip are re written everytime the user selects the year/filter. The code is a string in Java as it relies on if statements. However, whenever the user selects the year/filter the JavaScript functions do not work. The JavaScript code is repeated three times in the one class in separate if statements
This is the XML http Request code:
var year_selected = document.getElementById('year').innerHTML;
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("map").innerHTML = xhttp.responseText;
}
};
xhttp.open("GET", "/BCMapYear.html/"+year_selected, true);
xhttp.send();
JavaScript:
"<script type=\"text/javascript\">" +
"var transformMatrix = [1,0,0,1,0,0];"+
"var svg = document.getElementById('svg-map');"+
"var viewBox = svg.getAttributeNS(null, \"viewBox\").split(\" \");"+
"var centerX = parseFloat(viewBox[2])/2;"+
"var centerY = parseFloat(viewBox[3])/2;"+
"var matrixGroup = svg.getElementById(\"matrix-group\");"+
"var origMatrix = [1,0,0,1,0,0];"+
"function reset() {\n" +
" for(var i = 0; i < 6; i++) {\n" +
" transformMatrix[i] = origMatrix[i];\n" +
" } \n" +
" var newMatrix = \"matrix(\"+ transformMatrix.join(' ') + \")\";\n" +
" matrixGroup.setAttributeNS(null, \"transform\", newMatrix); \n" +
" \n" +
" };"+
"function pan(dx, dy) {"+
"transformMatrix[4] += dx;"+
"transformMatrix[5] += dy;"+
"var newMatrix = \"matrix(\"+ transformMatrix.join(' ') + \")\";"+
"matrixGroup.setAttributeNS(null, \"transform\", newMatrix);"+
"}"+
"function zoom(scale) {"+
"for(var i = 0; i < 4; i++) {"+
"transformMatrix[i] *= scale;"+
"}"+
"transformMatrix[4] += (1-scale) * centerX;"+
"transformMatrix[5] += (1-scale)* centerY;"+
"var newMatrix = \"matrix(\"+ transformMatrix.join(' ') + \")\";"+
"matrixGroup.setAttributeNS(null, \"transform\", newMatrix);"+
"}"+
"</script>"
+"<script type=\"text/ecmascript\">\n" +
" (function() {\n" +
" var svg = document.getElementById('svg-map');\n" +
" var tooltip = svg.getElementById('tooltip');\n" +
" var tooltipText0 = document.getElementById('tooltiptext0').firstChild;\n" +
" var tooltipText1 = document.getElementById('tooltiptext1').firstChild;\n" +
" var tooltipText2 = document.getElementById('tooltiptext2').firstChild;\n" +
" var tooltipText3 = document.getElementById('tooltiptext3').firstChild;\n" +
" var triggers = svg.getElementsByClassName('tooltip-trigger');\n" +
" for (var i = 0; i < triggers.length; i++) {\n" +
" triggers[i].addEventListener('mousemove', showTooltip);\n" +
" triggers[i].addEventListener('mouseout', hideTooltip);\n" +
" }\n" +
" function showTooltip(evt) {\n" +
" var CTM = svg.getScreenCTM();\n" +
" var x = (evt.clientX - CTM.e + 6) / CTM.a;\n" +
" var y = (evt.clientY - CTM.f + 20) / CTM.d;\n" +
" tooltip.setAttributeNS(null, \"transform\", \"translate(\" + x + \" \" + y + \")\");\n" +
" tooltip.setAttributeNS(null, \"visibility\", \"visible\");\n" +
" tooltipText0.data = evt.target.getAttributeNS(null, \"data-tooltip-text0\");\n" +
" tooltipText1.data = evt.target.getAttributeNS(null, \"data-tooltip-text1\");\n" +
" tooltipText2.data =
evt.target.getAttributeNS(null, \"data-tooltip-text2\");\n" +
" tooltipText3.data =
evt.target.getAttributeNS(null, \"data-tooltip-text3\");\n" +
" }\n" +
" function hideTooltip(evt) {\n" +
"
tooltip.setAttributeNS(null, \"visibility\", \"hidden\");\n" +
" }\n" +
" })()" +
" </script>";
On the Console it comes up uncaught referenceerror zoom is not defined
You can add (); after your block that you want executed.
(function(){
//Bunch of code...
})();
i try to plot the line(border right) in a table using javascript code . My code
plotPoints(item, index) {
var myElement = document.querySelector("#image-" + item + "-" + index);
(id is id = "image-0-4")
var position = this.getPosition(myElement);
console.log("The image is located at: " + position.x + ", " + position.y);
var first = index + 1;
var second = index + 2;
var third = index + 3;
var testDiv1 = document.getElementById("p1-" + item + "-" + first);
var position1 = this.getPosition(testDiv1);
console.log("The image is located at 1: " + position1.x + ", " + position1.y);
var testDiv2 = document.getElementById("p1-" + item + "-" + second);
var position2 = this.getPosition(testDiv2);
console.log("The image is located at 1: " + position2.x + ", " + position2.y);
var testDiv3 = document.getElementById("p1-" + item + "-" + third);
var position3 = this.getPosition(testDiv3);
console.log("The image is located at 1: " + position3.x + ", " + position3.y);
}
getPosition(el) {
var xPos = 0;
var yPos = 0;
while (el) {
if (el.tagName == "BODY") {
// deal with browser quirks with body/window/document and page scroll
var xScroll = el.scrollLeft || document.documentElement.scrollLeft;
var yScroll = el.scrollTop || document.documentElement.scrollTop;
xPos += (el.offsetLeft - xScroll + el.clientLeft);
yPos += (el.offsetTop - yScroll + el.clientTop);
} else {
// for all other non-BODY elements
xPos += (el.offsetLeft - el.scrollLeft + el.clientLeft);
yPos += (el.offsetTop - el.scrollTop + el.clientTop);
}
el = el.offsetParent;
}
return {
x: xPos,
y: yPos
};
}
I try to plot the line to connect the same number block .Using position function get all the block x and y position.
how to plot the line between the same number block( like number 1 block to connect line each column )
Description: A complex structure of HTML elements (rectangles) displayed on the screen, no overlaps, each rectangle having a distinct HTML id attribute (hence pickable by Selenium IWebDriver and C# code).
Target: I need programatically with Selenium and C# to create and trigger mousewheel event (via IJavaScriptExecutor or some other methods) on a selected rectangle element.
Q: How this can be done? Thank you
This is my implementation after investigating
//wheelTicks: negative for zoomin, positive to zoomout
public object zoomElementById(string elemId, int wheelTicks=1)
{
object response = null;
string myJavaScript =
// Callback (place in first!) used to notify the caller that the async callee is ready
" var callback = arguments[arguments.length - 1]; " +
" var maxIntervals = arguments[1]; " +
//ms
" var intervalDuration = 150; " +
" console.log('javascripting...', callback, arguments); " +
"var d = new Date(); " +
"var n = d.getTime(); " +
" var myZoomCenterElement = document.getElementById('" + elemId + "'); " +
// some debug output in the console
" console.log(myZoomCenterElement); " +
// *** THE CORE OF THE SOLUTION *** Creates proper WheelEvent object and triggers WheelEvent(Zoom)
" var box = myZoomCenterElement.getBoundingClientRect(); " +
" var boxMiddleX = Math.round((box.right + box.left )/2); " +
" var boxMiddleY = Math.round((box.bottom + box.top )/2); " +
" var myWheelableElement = document.getElementsByClassName('svg-tree-view')[0]; " +
" var wheelEventInitDict = { " +
" 'deltaX' : 0.0, " +
" 'deltaY' : -200.0, " +
" 'deltaZ' : 0.0, " +
" 'deltaMode' : 0, " +
" 'clientX' : boxMiddleX, " +
" 'clientY' : boxMiddleY " +
" }; " +
" var myWheelEvent = new WheelEvent('wheel', wheelEventInitDict); " +
" console.log(wheelEventInitDict, boxMiddleX, boxMiddleY, myWheelEvent); " +
" var myIntervalCounter = 0; " +
" var myInterval = setInterval(function(){ " +
" myWheelableElement.dispatchEvent(myWheelEvent); " +
" myIntervalCounter++; " +
" if (myIntervalCounter > maxIntervals) clearInterval(myInterval); " +
" }, intervalDuration); " +
" var sthToReturn = 'Returning: Nothing requested!'; " +
" var asyncAwaitInMiliSeconds = Math.ceil( 1.2 * intervalDuration * maxIntervals ); " +
// Triggers the callback (to indicate async ready)
" setTimeout( function(){ " +
" console.log((new Date()).getTime()-n); " +
" callback(sthToReturn); " +
" }, asyncAwaitInMiliSeconds); " +
""
;
_driver.Manage().Timeouts().SetScriptTimeout(new TimeSpan(0, 0, 20));
IJavaScriptExecutor js = _driver as IJavaScriptExecutor;
try
{
// addititonal args(optional) to be sent to the javascript func are put after the first arg
return response = js.ExecuteAsyncScript(myJavaScript, elemId, wheelTicks);
}
catch(UnhandledAlertException e)
{
Console.WriteLine("Error Occured! \n {0}", e.ToString() );
return null;
}
}
I'm trying to create a little text based rpg to put in practice what i learned of javascript. I tried two approaches, one is working and the other one isn't it, and I want to know why.
In the first one, I created an object "monster" with a method that sets all the properties of each monster (hit points, attack points, etc). The problem with this it's i have to write the properties one by one, and it makes the code too long for my taste.
/* Write JavaScript here */
/* Write JavaScript here */
$(document).ready(function() {
var hero = {
hitPoints: 13,
armorClass: 10,
attackBonus: 1,
weaponDamage: 7,
heroStats: function() {
return "Hero" + "<br/>" +
"Hit Points: " + this.hitPoints + "<br/>" +
"Armor Class: " + this.armorClass + "<br/>" +
"Attack Bonus: " + this.attackBonus + "<br/>" +
"Weapon Damage: " + this.weaponDamage;
},
alive: true
};
var monster = {
name: "",
hitPoints: 0,
armorClass: 0,
attackBonus: 0,
weaponDamage: 0,
monsterStats: function() {
return this.name + "<br/>" +
"Hit Points: " + this.hitPoints + "<br/>" +
"Armor Class: " + this.armorClass + "<br/>" +
"Attack Bonus: " + this.attackBonus + "<br/>" +
"Weapon Damage: " + this.weaponDamage;
},
monsterSelected: false,
selectMonster: function() {
if (this.monsterSelected === false) {
switch (Math.floor(Math.random() * 2) + 1) {
case 1:
this.name = "Werewolf";
this.hitPoints = 20;
this.armorClass = 8;
this.attackBonus = 4;
this.weaponDamage = 3;
this.monsterSelected = true;
break;
case 2:
this.name = "Goblin";
this.hitPoints = 15;
this.armorClass = 10;
this.attackBonus = 4;
this.weaponDamage = 3;
this.monsterSelected = true;
break;
}
}
},
alive: true
};
monster.selectMonster();
$(".hero_info").html(hero.heroStats());
$(".monster_info").html(monster.monsterStats());
$("button").click(function() {
battle(monster);
});
function battle(actualmonster) {
if (actualmonster.alive === false) {
actualmonster.monsterSelected = false;
actualmonster.selectMonster();
$(".monster_info").html(actualmonster.monsterStats());
$(".battle_info").html("");
actualmonster.alive = true;
} else {
var d20 = Math.floor(Math.random() * 20) + 1;
var d_wp = Math.floor(Math.random() * hero.weaponDamage) + 1;
if (d20 + hero.attackBonus > actualmonster.armorClass) {
$(".battle_info").html("You attack!: d20+" + hero.attackBonus + ": " + (d20 + hero.attackBonus) + " vs AC " + actualmonster.armorClass + "<br/>" + "You hit!: d" + hero.weaponDamage + ": " + d_wp);
actualmonster.hitPoints = actualmonster.hitPoints - d_wp;
$(".monster_info").html(actualmonster.monsterStats());
} else {
$(".battle_info").html("You miss!: d20+" + hero.attackBonus + ": " + (d20 + hero.attackBonus) + " vs AC " + actualmonster.armorClass);
}
if (actualmonster.hitPoints <= 0) {
actualmonster.hitPoints = 0;
$(".monster_info").html(actualmonster.monsterStats());
$(".battle_info").html("You killed the monster!");
actualmonster.alive = false;
} else {
var d20_m = Math.floor(Math.random() * 20) + 1;
var d_wp_m = Math.floor(Math.random() * monster.weaponDamage) + 1;
if (d20_m + actualmonster.attackBonus > hero.armorClass) {
$(".battle_info").append("<br/>Monster attacks you!: d20+" + actualmonster.attackBonus + ": " + (d20_m + actualmonster.attackBonus) + " vs AC " + hero.armorClass + "<br/>" + "Monster hits you!: d" + actualmonster.weaponDamage + ": " + d_wp_m);
hero.hitPoints = hero.hitPoints - d_wp_m;
$(".hero_info").html(hero.heroStats());
} else {
$(".battle_info").append("<br/>Monster miss!: d20+" + hero.attackBonus + ": " + (d20_m + monster.attackBonus) + " vs AC " + hero.armorClass);
}
}
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<p class="monster_info"></p>
<p class="battle_info"></p>
<p class="hero_info"></p>
<button type="button">Attack</button>
</body>
In the second one, instead of creating and object "monster", i make a constructor, so i could define the monsters in a shorter and simplier way (for example: var phantom = new monster (prop1, prop2, prop3...)). The issue comes when i tried select a random monster for each battle. I tried a lot of things, but the problem remains the same: if a create a random function to select the monsters, this works every time a click the attack button, making a mess. This is driven me crazy, and i have no idea what to do. Any suggestions? Thanks in advance.
$(document).ready(function() {
var hero = {
hitPoints: 13,
armorClass: 10,
attackBonus: 1,
weaponDamage: 7,
heroStats: function() {
return "Hero" + "<br/>" +
"Hit Points: " + this.hitPoints + "<br/>" +
"Armor Class: " + this.armorClass + "<br/>" +
"Attack Bonus: " + this.attackBonus + "<br/>" +
"Weapon Damage: " + this.weaponDamage;
},
alive: true
};
function monster(name, hitpoints, armorclass, attackbonus, weapondamage) {
this.name = name;
this.hitPoints = hitpoints;
this.armorClass = armorclass;
this.attackBonus = attackbonus;
this.weaponDamage = weapondamage;
this.monsterStats = function() {
return this.name + "<br/>" +
"Hit Points: " + this.hitPoints + "<br/>" +
"Armor Class: " + this.armorClass + "<br/>" +
"Attack Bonus: " + this.attackBonus + "<br/>" +
"Weapon Damage: " + this.weaponDamage;
},
this.selected = false;
this.alive = true;
}
function selectMonster() {
var werewolf = new monster("Werewolf", 5, 4, 4, 3);
var goblin = new monster("Goblin", 15, 4, 4, 3);
switch (Math.floor(Math.random() * 2) + 1) {
case 1:
if (werewolf.selected === false) {
werewolf.selected = false;
return werewolf;
}
break;
case 2:
if (goblin.selected === false) {
goblin.selected = false;
return goblin;
}
break;
}
}
$(".hero_info").html(hero.heroStats());
$(".monster_info").html(selectMonster().monsterStats());
$("button").click(function() {
battle(selectMonster());
});
function battle(actualmonster) {
if (actualmonster.alive === false) {
actualmonster.selected = false;
actualmonster.selectMonster();
$(".monster_info").html(actualmonster.monsterStats());
$(".battle_info").html("");
actualmonster.alive = true;
} else {
var d20 = Math.floor(Math.random() * 20) + 1;
var d_wp = Math.floor(Math.random() * hero.weaponDamage) + 1;
if (d20 + hero.attackBonus > actualmonster.armorClass) {
$(".battle_info").html("You attack!: d20+" + hero.attackBonus + ": " + (d20 + hero.attackBonus) + " vs AC " + actualmonster.armorClass + "<br/>" + "You hit!: d" + hero.weaponDamage + ": " + d_wp);
actualmonster.hitPoints = actualmonster.hitPoints - d_wp;
$(".monster_info").html(actualmonster.monsterStats());
} else {
$(".battle_info").html("You miss!: d20+" + hero.attackBonus + ": " + (d20 + hero.attackBonus) + " vs AC " + actualmonster.armorClass);
}
if (actualmonster.hitPoints <= 0) {
actualmonster.hitPoints = 0;
$(".monster_info").html(actualmonster.monsterStats());
$(".battle_info").html("You killed the monster!");
actualmonster.alive = false;
} else {
var d20_m = Math.floor(Math.random() * 20) + 1;
var d_wp_m = Math.floor(Math.random() * hero.weaponDamage) + 1;
if (d20_m + actualmonster.attackBonus > hero.armorClass) {
$(".battle_info").append("<br/>Monster attacks you!: d20+" + actualmonster.attackBonus + ": " + (d20_m + actualmonster.attackBonus) + " vs AC " + hero.armorClass + "<br/>" + "Monster hits you!: d" + actualmonster.weaponDamage + ": " + d_wp_m);
hero.hitPoints = hero.hitPoints - d_wp_m;
$(".hero_info").html(hero.heroStats());
} else {
$(".battle_info").append("<br/>Monster miss!: d20+" + hero.attackBonus + ": " + (d20_m + actualmonster.attackBonus) + " vs AC " + hero.armorClass);
}
}
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p class="monster_info"></p>
<p class="battle_info"></p>
<p class="hero_info"></p>
<button type="button">Attack</button>
The second approach is good but you're using it weird. selectMonster will randomly generate monster with some random logic and a call to new monster. But then you call selectMonster() a few times for no apparent reason.
Your code should look like:
var current_monster = selectMonster(); // note that you already have function named monster
$(".monster_info").html(current_monster.monsterStats());
$("button").click(function() {
battle(current_monster);
});
You can also go all the way with prototyping to define your monsters:
function Monster(name, hp, attack) {
this.name = name;
this.hp = hp;
this.attack = attack;
this.alive = true;
// etc
}
Monster.prototype.monsterStats = function() {
return this.name + "<br/>" +
"Hit Points: " + this.hitPoints + "<br/>" +
"Armor Class: " + this.armorClass + "<br/>" +
"Attack Bonus: " + this.attackBonus + "<br/>" +
"Weapon Damage: " + this.weaponDamage;
}
function Werewolf() {
Monster.call(this, "werewolf", 5, 4); // call parent
}
Werewolf.prototype = new Monster();
function Goblin() {
Monster.call(this, "goblin", 15, 3); // call parent
}
Goblin.prototype = new Monster();
var goblin = new Goblin();
console.log(goblin.hp); // 15
console.log(goblin.monsterStats()); // goblin <br /> etc..
In your monster constructor, you're doing stuff in your return statement that you probably don't want to be. When you have something like return x + 1, foo = 3, bar = false the expressions are evaluated left to right and the last one is returned. That is, you're retuning the state of this.alive instead of returning the this expected in the constructor.
Try refactoring your code to explicitly return the monster object you want to be created by the constructor, and see if you still have problems there. Generally, you want your return to stand on its own, to avoid confusion around syntax.
I have a tree structure where the elements can be dragged and dropped into another element. My objective is when a element or node from a tree is dragged and dropped to the external element I want a line to be drawn from the element of the tree to the external location.
I have the code separate for dragging and dropping. I tried to integrate the code into my tree structure and getting this error. I did see similar errors but could not get an exact idea about what exactly the error is. Here is the code that is giving me the error.
end: function(item, hover, placeholder, helper) {
if (placeholder.parent().length) {
var tree = $('#tree1').aciTree('api');
if (tree.isItem(item)) {
var id = tree.getId(item);
var label = tree.getLabel(item);
if (this._instance.jQuery.hasClass('any')) {
this._instance.jQuery.find('li:not(.aciSortablePlaceholder)').remove();
}
var item = $('<li id="item-' + id + '">' + label + '</li>');
var sourceId = id;
var destinationId = sourceId;
drawLine(sourceId, destinationId);
//This is how the function is called
placeholder.after(item).detach();
}
else {
placeholder.detach();
}
}
helper.detach();
}});
function drawLine(eTarget, eSource) {
setTimeout(function () {
var $source = eSource;
var $target = eTarget;
var originX = $source.offset().left + $source.width() + 20 + 4;
// In the $source.offset() I am getting the error.
var originY = $source.offset().top + (($source.height() + 20 + 4) / 2);
var endingX = $target.offset().left;
var endingY = $target.offset().top + (($target.height() + 20 + 4) / 2);
var space = 20;
var color = "black";
var a = "M" + originX + " " + originY + " L" + (originX + space) + " " + originY; // beginning
var b = "M" + (originX + space) + " " + originY + " L" + (endingX - space) + " " + endingY; // diagonal line
var c = "M" + (endingX - space) + " " + endingY + " L" + endingX + " " + endingY; // ending
var all = a + " " + b + " " + c;
console.log("New Line ----------------------------");
console.log("originX: " + originX + " | originY: " + originY + " | endingX: " + endingX + " | endingY: " + endingY + " | space: " + space + " | color: " + color );
console.log(all);
myLines[myLines.length] = svg
.path(all)
.attr({
"stroke": color,
"stroke-width": 1,
"stroke-dasharray": "-"
});
}, 1000);
PS: I am using firefox. The eTarget and eSource and getting the values as supplied.