I have a canvas with objects inside and have a event handler for object:selected. When I select the object, a div (vtover) appears at the mouse/touch pointer by pageX and pageY.
What I want to accomplish is to change the event handler from click to touch taphold using jQuery Mobile. I tried to put all code inside my taphold, but that didnt work.
How can I solve this?
chartdiv is the id of my canvas container
Code
canvas.observe("object:selected", function (e) {
$("#chartdiv").on("taphold", function (a) {
// tried to put below code inside this, but this didnt work out.
});
var obj = e.target;
$("#vtover").show();
$("#vtover").offset({
left: event.pageX,
top: event.pageY - 200
});
$("#vt_vol").val(myvol.toLocaleString("de-DE") + " " + unit);
$("#vt_period").val(myper + " Tage");
$("#vt_sump").val(sumper.toLocaleString("de-DE") + " " + unit);
$("#vt_diffp").val(Math.round((myvol * myper / sumper) * 100) + " %");
});
You can't do that, at least not like that, this should work:
var canvasHandler = {
obj : null
}
canvas.observe("object:selected", function (e) {
canvasHandler.obj = e.target;
});
$(document).on("taphold", "#chartdiv",function (a) {
// Now if you need selected canvas just use canvasHandler.obj
$("#vtover").show();
$("#vtover").offset({
left: event.pageX,
top: event.pageY - 200
});
$("#vt_vol").val(myvol.toLocaleString("de-DE") + " " + unit);
$("#vt_period").val(myper + " Tage");
$("#vt_sump").val(sumper.toLocaleString("de-DE") + " " + unit);
$("#vt_diffp").val(Math.round((myvol * myper / sumper) * 100) + " %");
});
Related
I've been trying to get a smooth scroll animation for a while now, but mainly in JS..
This hasn't been working out that well so I decided to try in CSS3.
Now I want to make this animation responsive by calling a JS function which adds the CSS rules for the animation responsive to the object the animation is for. Here is the JS code I've got so far. I'll also leave a Fiddle, but I'm new to that so things might not work right away.
function getTexts() {
var element = document.getElementsByClassName('toplink');
for (x = 0, len = element.length; x < len; x++){
var ID = element[x].textContent.toLowerCase();
var object = document.getElementById(ID);
console.log(object);
addCSSAnimator(ID);
}
}
function addCSSAnimator(el) {
var sheet = document.styleSheets[0];
var DOM = document.getElementById(el);
var Class = DOM.getAttribute("class");
var Parent = DOM.parentElement.getAttribute("id");
var rect = DOM.getBoundingClientRect();
var rule = ".toplink[ id= '"+el+"' ]:target - #"+Parent+" div."+Class+" {\n" +
"-webkit-transform: translateY( +"+rect.y.toPrecision(4)+'px'+" );\n" +
"transform: translateY( +"+rect.y.toPrecision(4)+'px'+" );\n" +
"}";
console.log("Stylesheet: ",sheet," object: ",DOM," Class: ",Class," offset X&Y:",rect.x," ",rect.y);
console.log(rule);
sheet.insertRule("body { background-color: 0; }", 1);
}
https://jsfiddle.net/dtj46c64/
You may try moving to jquery for this solution. Use document.ready and window.resize functions to handle the animation and also instead of for loop. use the jquery .each() function to get the elements. Try working around the following code i changed for you to go along with. Hope this puts you in the right direction to achieve your goal:
<script>
function getTexts() {
$(".toplink").each(function () {
let ID = $(this)
console.log(ID);
addCSSAnimator(ID);
});
}
function addCSSAnimator(el) {
var sheet = document.styleSheets[0];
var DOM = el;
var Class = DOM.attr("class");
var Parent = DOM.parent().attr("id");
var rect = DOM[0].getBoundingClientRect();
var rule = ".toplink[ id= '" + el + "' ]:target - #" + Parent + " div." + Class + " {\n" +
"-webkit-transform: translateY( +" + rect.top.toPrecision(4) + 'px' + " );\n" +
"transform: translateY( +" + rect.top.toPrecision(4) + 'px' + " );\n" +
"}";
console.log("Stylesheet: ", sheet, " object: ", DOM, " Class: ", Class, " offset X&Y:", rect.left, " ", rect.top);
console.log(rule);
sheet.insertRule("body { background-color: 0; }", 1);
}
$(window).on('resize', function () {
getTexts();
});
$(document).ready(function () {
getTexts();
});
</script>
Notice i changed the rect.y to rect.top as on some browsers the getBoundingClientRect fucntion does not return x and y values but left and top are always filled.
Also dont know why you are getting id of the parent of the object as there is no id set to the parent of the anchor class="toplink" so it will always return as null or empty.
Sorry for not a 100% answer as got busy but i hope the solution so far i suggested will help you tweak and find what your looking for.
I am currently using an event attached to $(document)
I tried changing it to different elements on the page, but nothing happens.
This is my starting code for a basic context menu
$(document).bind("contextmenu", function (event) {
event.preventDefault();
if ($(".context-menu") != null) {
$(".context-menu").remove();
}
$("<div class='context-menu'>" +
"<ul>" +
"<a href=javascript:null onclick=''><li>Do Something</li></a>" +
"</ul>"+
"</div>")
.appendTo("body")
.css({ top: event.pageY + "px", left: event.pageX + "px" });
});
$(document).bind("click", function (event) {
$(".context-menu").remove();
});
Clarification
I am not trying to create a context menu. I am trying to create multiple ones, each one is triggered by right clicking a different element.
For instance, if you right-click a div, you get a context menu with the ability to change the div's color, if you right-click on the document you get a different context menu, and if you right-click on the header, yet a different context menu.
Can this be done?
This is my attempt that doesn't work
$(document).bind("contextmenu", function (event) {
event.preventDefault();
});
$(document).bind("click", function (event) {
$(".context-menu").remove();
});
$("#divID").mousedown(function (e) {
if (e.button == 2) {
if ($(".context-menu") != null) {
$(".context-menu").remove();
}
$("<div class='context-menu'>" +
"<ul>" +
"<a href=javascript:null onclick=''><li>Do Somthing</li></a>" +
"</ul>" +
"</div>")
.appendTo("divID")
.css({ top: event.pageY + "px", left: event.pageX + "px" });
return false;
}
return true;
});
My fiddle maybe help you!!!
Just Sample code
$(document).bind("contextmenu", function (event) {
event.preventDefault();
});
$(document).on("mousedown","#divID",function (e) {
if ($(".context-menu").length != 0) {
$(".context-menu").remove();
}
if (e.button == 2) {
event.preventDefault();
$("<div class='context-menu'>" +
"<ul>" +
"<a href=javascript:null onclick=''><li>Do Somthing</li></a>" +
"</ul>" +
"</div>")
.appendTo($(this))
.css({ top: event.pageY + "px", left: event.pageX + "px" });
return false;
}
return true;
});
Jquery on
bind event parent but targeting child
Without writing out a whole script for you, you want to get
e.target.tagName or event.srcElement.tagName (depending on browser)
from the event listener.
This will give you A, IMG, TEXTAREA etc.
I'm trying to implement hammer.js to swipe pages (like a book) and I did it. The problem is that this works
var idHammer1 = document.getElementById("pageHoja1")
//var hammertime = new Hammer(myElement, hammerOptionsPan);
var objHammer1 = new Hammer(idHammer1);
objHammer1.on('panleft panright', function(ev)
{
//DBLog("obj1 - gSceneActual Antes: " + gSceneActual + " // X: " + ev.center.x + " Y: " + ev.center.y);
if (ev.type==='panleft')
{
if (!(gSceneActual===2))
{
gSceneActual = 2;
$(":mobile-pagecontainer").pagecontainer("change", "#pageHoja2", { transition: "slide", reverse: false});
}
}
else if (ev.type==='panright')
{
}
});
but this doesn't:
var fSwipe1 = function(ev)
{
//DBLog("obj1 - gSceneActual Antes: " + gSceneActual + " // X: " + ev.center.x + " Y: " + ev.center.y);
if (ev.type==='panleft')
{
if (!(gSceneActual===2))
{
gSceneActual = 2;
$(":mobile-pagecontainer").pagecontainer("change", "#pageHoja2", { transition: "slide", reverse: false});
}
}
else if (ev.type==='panright')
{
}
}
var idHammer1 = document.getElementById("pageHoja1")
//var hammertime = new Hammer(myElement, hammerOptionsPan);
var objHammer1 = new Hammer(idHammer1);
objHammer1.on('panleft panright', fSwipe1(ev))
and this also don't work
function fSwipe1(ev)
{
//DBLog("obj1 - gSceneActual Antes: " + gSceneActual + " // X: " + ev.center.x + " Y: " + ev.center.y);
if (ev.type==='panleft')
{
if (!(gSceneActual===2))
{
gSceneActual = 2;
$(":mobile-pagecontainer").pagecontainer("change", "#pageHoja2", { transition: "slide", reverse: false});
}
}
else if (ev.type==='panright')
{
}
}
and since I need to add this event to many pages (variable #) I cant hardcode it... How can I make it variable inside a cycle?
Thanks!
Ah, without knowing the extent of the errors, I do see:
objHammer1.on('panleft panright', fSwipe1(ev));
Here, you are rendering the function automatically, but what you actually want is to use a closure so that the function does not get rendered until the event gets hit. I'm not sure what ev represents, but if it is the event object, then this should work:
objHammer1.on('panleft panright', fSwipe1);
Where all you are doing is passing in the function that you want to be the callback and the even will automatically call this function and pass the event object as the first parameter.
A few other things that I notice:
make sure that you include the javascript library for Hammer
Make sure that gSceneActual is defined before it is evaluated at gSceneActual===2
Make sure that jQuery library is included
this code works:
var myElement = document.getElementById("red");
setInterval(function() {
console.log("Left:" + myElement.offsetLeft + "px | Top:" + myElement.offsetTop + "px");
}, 1000);
This prints out the position(x, y) every second
But If I try and change it to using objects:
function Enemy(id){
this.id = getElementById(id);
this.getCoordinates = function(){
setInterval(function() {
console.log("Left:" + this.id.offsetLeft + "px | Top:" + this.id.offsetTop + "px");
}, 1000);
}
}
$(document).ready(function(){
var enemy = new Enemy("red");
enemy.getCoordinates();
});
It prints out nothing - and I can't see where my mistake is.
In a setInterval or setTimeout (or any event handler like onclick) the this variable refers to the global object. In a browser that's window.
In modern browsers you can do this:
setInterval((function() {
console.log("Left:" + that.id.offsetLeft + "px");
}).bind(this), 1000); // <------- bind
Otherwise all other solutions are basically similar to your first piece of code.
Note that there is an implementation of bind() in pure js from Mozilla that can be ported to older browsers. Search for it on MDN.
The problem is that the value of "this" is changing within the setInterval. The fix is to change it to:
function Enemy(id){
this.id = document.getElementById(id);
var self = this;
this.getCoordinates = function(){
setInterval(function() {
console.log("Left:" + self.id.offsetLeft + "px | Top:" + self.id.offsetTop + "px");
}, 1000);
}
}
function Enemy(id){
this.id = document.getElementById(id);
this.getCoordinates = function(){
var element = this.id;
setInterval(function() {
console.log("Left:" + element.offsetLeft + "px | Top:" + element.offsetTop + "px");
}, 1000);
}
}
$(document).ready(function(){
var enemy = new Enemy("red");
enemy.getCoordinates();
});
As slebetman said, the 'this' variable is not what you expected. Try saving it in a 'that' variable, which can be accessed in different scopes.
function Enemy(id){
var that = this; // reference to 'this' that can be used in other scopes
that.id = document.getElementById(id);
that.getCoordinates = function(){
setInterval(function() {
console.log("Left:" + that.id.offsetLeft + "px | Top:" + that.id.offsetTop + "px");
}, 1000);
}
return that;
}
Im trying to cause a canvas element to be added to the DOM and then removed after a set time. The killbox() function gets called, but the element is not removed. I believe I have the syntax right, and that there is some underlying issue with removing dynamically added DOM elements.
//con is short for console.log()
function spawnCanvas(e) {
con(e);
var boxheight=50;
var boxwidth=50;
var xpos = e.clientX - boxwidth/2;
var ypos = e.clientY - boxheight/2;
var id = xpos.toString() + ypos.toString();
con("id:" + id);
var tag = "<canvas width='" + boxwidth +
"' height='" + boxheight +
"' style='position:absolute; border:1px solid #000; left:" +
xpos + "px; top:" + ypos + "px;' id='" + id + "'></canvas>";
con(tag);
var t = $(tag);
$("body").append(t);
var p = setTimeout("killbox(" + id + ")", 1500);
}
function killbox(id){
con("in killbox. id:" + id);
$('#id').remove();
}
Within killbox you are removing the element with the literal id id. Instead try;
$('#' + id).remove();
The above will remove the element that has the id that the "id" variable is set to.
Are you sure you don't want $("#" + id).remove();?
because you are searching with an element with the ID id, but you rather wanted to pass the parameter from the function
function killbox(id){
con("in killbox. id:" + id);
$('#'+id).remove();
}