How to dynamically add an ondragstart event to a dynamically created div - javascript

There are a couple of questions that seem to ask this question, but no one accepted answers and nothing has worked for me.
I have a 'group' button that when it's clicked, will dynamically create a 'group' div (I then append some pre-selected 'child' divs within it)
However I need the new 'group' div to be draggable.
I can set the draggable attribute dynamically, no problem.
But being draggable is not much good without the ondragstart() event, and no matter what I've tried, I can't get this assigned.
I am using jQuery which may have a bearing.
The latest iteration of my code is (this appears in an init() function that is called from body.onload):
var group=$(document.createElement('div'));
group.attr({id: 'group'+grpcount});
group.attr({draggable: "true"});
group.addClass('group');
group.html("<span class='group'>Group"+grpcount+"</span>");
$('#boundary').append(group);
document.getElementById('group'+grpcount).addEventListener("startdrag",drag);
But I have also tried various combinations of jQuery .bind:
group.bind("dragstart", drag(ev));
group.bind("dragstart", function(ev){drag(ev);});
All to no avail.
I have a drag function already defined (and I've tried putting it before and after the code above):
function drag(ev) {
ev.dataTransfer.setData("Text",ev.target.id+":"+ev.pageX+":"+ev.pageY);
}
I hope there is something glaringly obvious that I just can't see.
Can somebody solve this?

You'll be better to take a look at Jquery UI draggable here
and if you dont know yet, you can call multiple jquery finctions in a chain, so your code looks more readable like below:
var group=$('div').attr('id', 'group'+grpcount)
.addClass('group')
.html("<span class='group'>Group"+grpcount+"</span>");
$('#boundary').append(group);
and instead of
document.getElementById('group'+grpcount).addEventListener("startdrag",drag);
use this
group.draggable({
start:function(event, ui){
//this is where dragging starts when you push mousedown and move mouse
},
drag:function(event, ui){
//this function will be called after drag started each time you move your mouse
}
stop:function(event, ui){
//this is where you release mouse button
}
})
this jquery draggable widget with droppable widget will ease your life if you really want to implement complex drag-and-drop functionality

I made this:
function drag(ev) { alert('Hi'); }
var grpcount = 21;
var group=$(document.createElement('div'));
group.attr({id: 'group'+grpcount});
group.attr({draggable: "true"});
group.addClass('group');
group.html("<span class='group'>Group"+grpcount+"</span>");
group.bind("dragstart", function(ev){drag(ev);});
$('#boundary').append(group);
See the working fiddle here: http://jsfiddle.net/nxcSz/

Related

How can I keep mega sub menu open after mouse leaves top navigation button?

I am new to jQuery. I am trying to set up a mega drop down that is 100% width on the screen but the content is centered. Also the top navigation buttons are centered.
How can I keep the sub content area open after the mouse leaves the top button?
Here is the fiddle: http://jsfiddle.net/uf1107qs/
$('.top1').on('mouseenter', function () {
$('.sub1').slideDown(200).addClass('.abTop');
$('.fades1').delay(50).fadeIn(200);
});
$('.top1').on('mouseleave', function () {
$('.sub1').delay(600).slideUp(200).removeClass('.abTop');
$('.fades1').fadeOut(0);
});
did you want the .subX and .fades1 keep showing and never closed?
perhaps this is this what you want?
JSFIDDLE
Edit :
sorry for my misunderstanding before. You can achieve that by using setTimeout rather than delay, here's the result : JSFIDDLE, it's still ugly though, because there are many repeated code inside it.
Basically you need to setTimeout when mouseleave the top, and clearTimeout when mouseenter the top or sub
Other Way :
the other way around to achieve it, you can use only CSS by using CSS property like position, visibilty, opacity, z-index like in this example on JSFIDDLE
Instead of using delay, or a timeout.. you can use what's called a callback function, which is supported by most jQuery built-in functions. This is your code:
$('.top1').on('mouseenter', function () {
$('.sub1').slideDown(200).addClass('.abTop');
$('.fades1').delay(50).fadeIn(200);
});
Here is my version using the concept of a "callback":
$('.top1').on('mouseenter', function () {
//see the difference?
$('.sub1').slideDown(200, function(){
$('.fades1').fadeIn(200);
}).addClass('.abTop');
});
Essentially what is happening, is that slideDown() is able to accept an optional parameter that is function. This function will then get triggered only AFTER 200ms have passed (Since you have it set to slideDown(200)).
So callback function in this case, is simple a function that is called, only after the parent function (for simplicity sake) is done doing what it's supposed to do. For more info:
http://www.w3schools.com/jquery/jquery_callback.asp
ALSO
Since you are new to jQuery, you should definitely check out the hover() function. You will be able to simplify your code by probably half the amount of JS lines, and be much more readable!
http://api.jquery.com/hover/

Jquery on mousedown not working on dynamically generated elements

So i'm trying to create a js/css "wave game" like tower defense ones.
When all the pre-generated enemys from first wave are dead, it spawns the second wave and so on.
So far so good.
The problem is that i just can't attack mobs dynamically spawned within second wave.
I used to try .live() in similar cases, but its deprecated, so i'm trying .on(), as instructed
$('.enemy').on('mousedown' , function(event) {
//attack code
}
Its working fine for initial mobs (1st wave) but it still just not working on dynamic mobs (>= 2nd wave)
Help, guys, please?
You need to specify an element that is already there when the DOM is created. In the parameters, you specify the elements you want to add the mousedown method. By simply assigning $('.enemy'), it will attach the method to those that are already present in the DOM.
$('body').on('mousedown', '.enemy', function(event) {
//attack code
}
As Wex mentioned in the comments, instead of writting $('body') you should use the container's name (the container which wraps the .enemy elements. This way, when a .enemy element is added, the event doesn't need to bubble all the way up to the body tag.
The binding '.on()' works only with the content that created earlier then the script ran.
So one solution could be you bind the event to the parent element.
$('.PARENT_ELEMENT').on('mousedown', '.enemy', function(event){
// your code here
}
That should do it.
I made this google like drop down suggestions search box and I faced a problem similar to yours where there was suggestions disappearing before the re-direct happened. I overcame it by using and modifing vyx.ca answer:
var mousedownHappened = false;
var clicked_link;
$("#search-box").blur(function(e) {
if (mousedownHappened)// cancel the blur event
{
mousedownHappened = false;
window.location.href = clicked_link;
} else {
// no link was clicked just remove the suggestions box if exists
if ($('#search-btn').next().hasClass('suggestions')) {
$(".suggestions").remove();
}
}
});
//attaching the event to the document is better
$(document).on('mousedown', '.suggestions a', function() {
clicked_link= $(this).attr('href');
mousedownHappened = true;
});

Reverse onClick Event

I am a genuine javascript novice and looking some pointers in my learning - not homework nor is it anything commercial.
I have a function here which shows an element which is hidden due to the first 2 lines of the function. I start by clicking the heading and the 2 hidden divs appear, which is exactly what I wanted to happen. However, now when I use this second function, it won't return to it's windown onload state. Why is this? Is there a better way to achieve this?
1st Function
$(window).ready(function(){
$('.miniC').css("display", "none");
$('.miniI').css("display", "none");
$(".heading").click(function(){
$('.miniC').slideDown();
$('.miniI').slideDown();
$('.miniC').show();
$('.miniI').show();
});
});
2nd Function (Reverse)
$(window).ready(function(){
$(".hideOut").click(function(){
$('.miniC').slideUp();
$('.miniI').slideUp();
$('.miniC').hide();
$('.miniI').hide();
});
});
Thanks in advance and any reference to good reading material is appreciated.
* Corrected Missing closing quote - this was a mistake of me typing it into Stack Overflow - Sorry! *
It seems like you want to toggle the visibility of an element, and since you're already sliding it, why not just use slideToggle:
$(".miniC").css("display", "none");
$(".miniI").css("display", "none");
$(".heading").click(function () {
$(".miniC").slideToggle();
$(".miniI").slideToggle();
});
Example
You shouldn't need to call .hide() and .show() - they will be dealt with as part of the slide functions. However, you're calling them immediately after the slide, but that takes a while to complete (400ms by default) meaning that .hide() fires before .slideUp() completes.
Outside the question scope, but still applicable.
$('.miniC').css("display", "none");
$('.miniI').css("display", "none");
This part of the page functionality should probably in CSS, which will result in the browser rendering the initial paint of the page correctly. In your case the browser paints the "miniC" and "miniI" elements, then your jQuery code updates the CSS display property to "none" for both individually. Triggering two additional repaints of the page. So, basically with the jQuery code you are drawing the page three times for an effect that could achieved with a single paint.
Then like Charlie said add a listener for the click.
$(".heading").click(function () {
$(".miniC").slideToggle();
$(".miniI").slideToggle();
});
Because slideUp() and hide() are written inside the click event. So, it wont fire on window ready, but only onclick of $(".hideOut").
There is a typo in your first function.
a single quote is missing in the line:
$('.miniC).show();

How do I inherit jQuery effects when i introduce a new DOM

I have a slideshow that i replace an unordered list within the slide show, the images change but any effects are not inherited. this is the script that introduces a new DOM:
jQuery("#kwick1").click(function () {
jQuery('#photography').load('/design.html #photography');
});
jQuery("#kwick2").click(function () {
jQuery('#photography').load('/design.html #design');
});
how do i get the jQuery slideshow to inherit this new list of images??
i both these functions and the slide show function in the same file.
I have a
jQuery(document).ready(function() {
that loads the slideshow script.
You have to let us know what slideshow plugin you are using. Regardless, you probably just need to destroy your old slideshow instance and restart it. Something like:
//start slideshow on
var slideshow = $('#slideshow').cycle();
slideshow.start();
$('#button').click( function() {
//depending on plugin api maybe stop, add and start again
slideshow.stop();
slideshow.addImages();
slideshow.start();
//or perhaps just destroy old slideshow and restart
slideshpw = $('#slideshow').cycle();
});
To attach events to newly added elements you should use live() or delegate();
jQuery('.yourselector').live('click', function(){
//do something on click
});
Instead of attaching events to each of elements, you should learn how to use event delegation. That way you can attach single event listener on some container ( or even document ) and catch the events as they bubble up.
Additionally it will make your code look much cleaner and easier to understand.
http://lab.distilldesign.com/event-delegation/
http://net.tutsplus.com/tutorials/javascript-ajax/quick-tip-javascript-event-delegation-in-4-minutes/
http://www.sitepoint.com/javascript-event-delegation-is-easier-than-you-think/
P.S. , if you put your code at the bottom of the HTML ( before </body> ) then, when it triggers , it will already be an "onDomReady" event.

Listen for change events in forms: JQuery

I have a form with an id of "wizard" - I only have select elements in this form. This form is in a lightbox using the JQuery plugin fancybox:
I want to know when any of these have been changed using JQuery. How can I do this? I currently have:
$('form#wizard select[name=servers], form#wizard select[name=cores]').change(function() {
var channels = parseInt($('form#wizard select[name=servers]').val(), 10) * parseInt($('form#wizard select[name=cores]').val(), 10);
$('#yellow').val(channels);
});
EDIT - I have the above wrapped in $(document).ready(function() {...}
However, it does not work, it does not even get run. I have put alerts in there and they never show up. The above only works when the above is a div that I have removed the display:none from, strange! So I am looking for a different implementation to get around this as I need that lightbox as it is.
I really need help on this.
Thanks all
The jQuery change function only binds those elements that are present when the domready event fires. If the lightbox plugin you are using is dynamically creating elements, you should be using jQuery's live function to "bind your handler to all current - and future matched elements".
Change this:
$('your selector').change(function() { /* code ... */ });
with this:
$('your selector').live('change', function() { /* code ... */ });

Categories

Resources