jQuery - coordinated event handler for array of $.post deferred objects - javascript

I have an $.each block that iterates over all the select elements on a form, and invokes a $.post for each one.
var deferredObjects = [];
$('#form').find('select').each(
function(i, o) {
var jqxhr = $.post("data.json", {} ));
deferredObjects.push( jqxhr) ;
}
);
I'd like to have an event-handler fire when all the post operations are complete. I'm collecting all the deferred objects returned from the post method into an array. I was hoping to use something like
$.when( ... ).then( ... );
but I can't see how to fit this construct into my scenario?

You can use promise() (it will execute once all collective actions are done) available in jquery. For example, you can see
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>promise demo</title>
<style>
div {
height: 50px;
width: 50px;
float: left;
margin-right: 10px;
display: none;
background-color: #090;
}
</style>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
<button>Go</button>
<p>Ready...</p>
<div></div>
<div></div>
<div></div>
<div></div>
<script>
$( "button" ).on( "click", function() {
$( "p" ).append( "Started..." );
$( "div" ).each(function( i ) {
$( this ).fadeIn().fadeOut( 1000 * ( i + 1 ) );
});
$( "div" ).promise().done(function() {
$( "p" ).append( " Finished! " );
});
});
</script>
</body>
</html>
https://jsfiddle.net/mzo5Lhbk/
Also, read these links if you want to use when()
https://api.jquery.com/jquery.when/
Hope it will help you!!!

You can use the spread syntax like this.
$.when(...deferredObjects)

Related

Element created on keydown using JavaScript createElement() method won't work with the jQuery draggable() method

I'm working on a drag and drop project where items can be added to a work area and dragged to be positioned. I am trying to use a key code to create multiple of the same kind of element, all of which can be dragged. The jQuery function works as long as the draggable element is created when the page loads, but if it's created using a function, the draggable() method isn't working on it. Is there a way to get the function to recognize the element created with a function?
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Draggable Div Test</title>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<style>
.test {
width: 50px;
height: 50px;
}
</style>
</head>
<body>
<div id="area" style="border: 1px solid black; width: 500px; height: 500px;"> </div>
<script>
var area = document.getElementById("area");
function duplicate(e) {
switch(e.keyCode) {
case 49:
var test = document.createElement("div");
test.classList.add("test");
test.classList.add("draggable");
console.log(test.classList)
test.style.backgroundColor = "blue";
area.appendChild(test);
break
}
}
document.addEventListener("keydown", duplicate)
$( function() {
$( ".test" ).draggable();
} );
</script>
</body>
</html>
Thanks
jQuery draggable has a function called clone:
$(function() {
i = 0
$("#draggable").draggable({
helper: 'clone',
appendTo: "#droppable",
});
$("#droppable").droppable({
accept: "#draggable",
});
i++;
var $obj = ui.helper.clone().attr( 'data-name', 'newelementdropped' +i).draggable({
stop : function (event, ui) {
YOUR CODE
});
}
See this answer: Jquery draggable(), clone() to append div...Pls Fiddle my jsfiddle
Just re-initalize the plugin after you insert the element.
Something like:
$(".test").draggable("destroy").draggable();

How to correctly read height of iframe's contents after changing the contents in jQuery

I am programming a website creator where user is allowed to visually create some website structure in an iframe.
The iframe's height must get updated always when the iframe's content is updated. I'm having some difficulties in understanding why height of iframe's content is sometimes read incorrectly in JavaScript after dynamically changing the content. I made a test script which shows the thing:
http://vickcreator.com/test/test.php
with iframe here: http://vickcreator.com/test/test2.php
As you can see by looking in source code in browser (or below) the first button fills the iframe with many boxes and immidiately tries to update iframe's height which does not work - it looks like the height is not updated yet in DOM (or something like that), so I though the second button will do - it uses 1 second of delay (doesn't really matter how many seconds, I tried even 5 sec), but no, here height is read wrong (a little less than should be) which results in vertical scroll bar (tested on Firefox and Chrome) - WHY ? Then pressing "set height" fixes the issue. The same happens (first "clear" to reset) when pressing "ONLY fill", then"set height" - then pressing "set height" second time fixes this.
Two questions:
is there any event saying that updating of iframe's content has completed ?
how to correctly read the outerHeight ? I tried:
$( '#iframe' ).contents().find( 'html' ).outerHeight();
$( '#iframe' ).contents().find( 'body' ).outerHeight();
$( '#iframe' ).contents().find( '#wrapper' ).outerHeight();
$( '#iframe' ).contents().outerHeight();
None of these worked.
Below is source code of both files. I didn't use code snippet in StackOverflow because it does not allow me to use iframes.
I can update the code on my server if you need. Thanks for help.
test.php:
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="utf-8" />
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.0.min.js"></script>
<script type="text/javascript" src="https://searchcode.com/codesearch/raw/73742722/"></script>
<script type="text/javascript">
function setHeight()
{
var newHeight = $( '#iframe' ).contents().find( 'html' ).outerHeight();
$( '#iframe' ).height( newHeight );
$( '#heightText' ).html( newHeight );
}
function fill()
{
for( i=0; i<1000; ++i )
{
$( '#iframe' ).contents().find( '#wrapper' ).append( '<div class="box"></div>' );
}
}
function go( delay )
{
fill();
if( ! delay )
{
setHeight();
}
else
{
$( document ).everyTime( 1000, function(i)
{
setHeight();
}, 1 );
}
}
function clearContent()
{
$( '#iframe' ).contents().find( '#wrapper' ).empty();
$( '#iframe' ).height( '500px' );
$( '#heightText' ).html( 500 );
}
</script>
<style type="text/css">
.box { border:1px dashed black; height:50px; width:50px; margin:5px; display:inline-block; }
.coloured { background: darkgreen; }
</style>
</head>
<body>
<button onclick="go( false );">Fill and set height with NO delay</button>
<button onclick="go( true );">Fill and set height WITH delay (1s)</button>
<button onclick="setHeight();">Set height</button>
<button onclick="fill();">ONLY fill</button>
<button onclick="clearContent();">Clear</button>
Height:<span id="heightText"></span>
<iframe id="iframe" style="width:100%; height:500px;" src="test2.php"></iframe>
</body>
</html>
test2.php (iframe):
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="utf-8" />
<style type="text/css">
.box { border:1px dashed black; height:50px; width:50px; margin:5px; display:inline-block; }
.coloured { background: darkgreen; }
</style>
</head>
<body>
<div id="wrapper">
</div>
</body>
</html>

JQUERY UI DatePicker Calendar not showing

I was working on JQuery UI Date Picker.
before it was working great but now the calendar won't show up.
any ideas?
here's my code.
http://pastebin.com/L4j2TmyY
my code is too long so i placed it in pastebin.
I follow this exactly but calendar is not showing
http://jqueryui.com/datepicker/
I think you should download all the JavaScript files into your project folder and call the JavaScript files.
Example :
Calling JavaScript from external URL (Not working)
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>undelegate demo</title>
<style>
button {
margin: 5px;
}
button#theone {
color: red;
background: yellow;
}
</style>
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
<button id="theone">Does nothing...</button>
<button id="bind">Bind Click</button>
<button id="unbind">Unbind Click</button>
<div style="display:none;">Click!</div>
<script>
function aClick() {
$( "div" ).show().fadeOut( "slow" );
}
$( "#bind" ).click(function() {
$( "body" )
.delegate( "#theone", "click", aClick )
.find( "#theone" ).text( "Can Click!" );
});
$( "#unbind" ).click(function() {
$( "body" )
.undelegate( "#theone", "click", aClick )
.find( "#theone" ).text( "Does nothing..." );
});
</script>
</body>
</html>
Calling from project Folder(Working fine)
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>undelegate demo</title>
<style>
button {
margin: 5px;
}
button#theone {
color: red;
background: yellow;
}
</style>
<script src="jQuery.js"></script>
</head>
<body>
<button id="theone">Does nothing...</button>
<button id="bind">Bind Click</button>
<button id="unbind">Unbind Click</button>
<div style="display:none;">Click!</div>
<script>
function aClick() {
$( "div" ).show().fadeOut( "slow" );
}
$( "#bind" ).click(function() {
$( "body" )
.delegate( "#theone", "click", aClick )
.find( "#theone" ).text( "Can Click!" );
});
$( "#unbind" ).click(function() {
$( "body" )
.undelegate( "#theone", "click", aClick )
.find( "#theone" ).text( "Does nothing..." );
});
</script>
</body>
</html>
As i saw your pastebin you are loading two jQuery libraries, which is not recommended, although you can use it with jQuery.noConflict(). So the quick fix is this:
Remove this library:
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
#Kim Carlo
I continue with #Rohit Bandooni's answer.
As his answer, it should work correctly.
A pastebin cloned from your paste: http://pastebin.com/2yNiXy44
I did some changes:
- comment yours 2 "die"
- change the method name (search for text "CHANGE_BY_ME" in pastebin)
I run on my EasyPHP, it works well: http://imgur.com/kfmLkLY,lHsEUyv (2 images for 2 controls)
I found only 2 date controls on your page.

jQuery sliding upon fadeOut

I'm looking at the jQuery API, and they have this example:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>fadeOut demo</title>
<style>
span {
cursor: pointer;
}
span.hilite {
background: yellow;
}
div {
display: inline;
color: red;
}
</style>
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
<h3>Find the modifiers - <div></div></h3>
<p>
If you <span>really</span> want to go outside
<span>in the cold</span> then make sure to wear
your <span>warm</span> jacket given to you by
your <span>favorite</span> teacher.
</p>
<script>
$( "span" ).click(function() {
$( this ).fadeOut( 1000, function() {
$( "div" ).text( "'" + $( this ).text() + "' has faded!" );
$( this ).remove();
});
});
$( "span" ).hover(function() {
$( this ).addClass( "hilite" );
}, function() {
$( this ).removeClass( "hilite" );
});
</script>
</body>
</html>
This is similar to my code. Is there a way to make the remaining paragraph slide to the left when the phrase is removed, to make that transition smoother?
I think you will have to animate the p tag. It's the parent of what you have clicked on, so something like this should work...
$( this ).remove().parent('p').animate({
'margin-left' : '-500px'
}, 300);

jQuery UI Sortable -- How can I cancel the click event on an item that's dragged/sorted?

I have a jQuery UI Sortable list. The sortable items also have a click event attached. Is there a way to prevent the click event from firing after I drag an item?
$().ready( function () {
$('#my_sortable').sortable({
update: function() { console.log('update') },
delay: 30
});
$('#my_sortable li').click(function () {
console.log('click');
});
});
#my_sortable li {
border: 1px solid black;
display: block;
width: 100px;
height: 100px;
background-color: gray;
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.1/jquery-ui.min.js"></script>
<ul id="my_sortable">
<li id="item_1">A</li>
<li id="item_2">B</li>
<li id="item_3">C</li>
</ul>
I had the same problem and since my sortable items contained three or four clickable items (and the number was variable) binding/unbinding them on the fly didn't really seem an option. However, by incident I specified the
helper : 'clone'
option, which behaved identically to the original sortable in terms of interface but apparently does not fire click events on the dragged item and thus solves the problem. It's as much a hack as anything else, but at least it's short and easy..
If you have a reference to the click event for your li, you can unbind it in the sortable update method then use Event/one to rebind it. The event propagation can be stopped before you rebind, preventing your original click handler from firing.
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.1/jquery-ui.min.js"></script>
<script type="text/javascript" charset="utf-8">
var myClick = function () {
console.log('click');
};
$().ready( function () {
$('#my_sortable').sortable({
update: function(event, ui) {
ui.item.unbind("click");
ui.item.one("click", function (event) {
console.log("one-time-click");
event.stopImmediatePropagation();
$(this).click(myClick);
});
console.log('update') },
delay: 30
});
$('#my_sortable li').click(myClick);
});
</script>
<style type="text/css" media="screen">
#my_sortable li {
border: 1px solid black;
display: block;
width: 100px;
height: 100px;
background-color: gray;
}
</style>
</head>
<body>
<ul id="my_sortable">
<li id="item_1">A</li>
<li id="item_2">B</li>
<li id="item_3">C</li>
</ul>
</body>
</html>
If you for some reason don't want to use the helper:'clone' trick, this worked for me. It cancels the click event on an item that is dragged. jQuery adds the class ui-sortable-helper to the dragged element.
$('.draggable').click(clickCancelonDrop);
function clickCancelonDrop(event) {
var cls = $(this).attr('class');
if (cls.match('ui-sortable-helper'))
return event.stopImmediatePropagation() || false;
}
$('.selector').draggable({
stop: function(event, ui) {
// event.toElement is the element that was responsible
// for triggering this event. The handle, in case of a draggable.
$( event.toElement ).one('click', function(e){ e.stopImmediatePropagation(); } );
}
});
This works because "one-listeners" are fired before "normal" listeners. So if a one-listener stops propagation, it will never reach your previously set listeners.
We can also use a flag on the stop event that and check that flag on the click event.
var isSortableCalled = false;
$('#my_sortable').sortable({
stop: function(event, ui){
isSortableCalled = true;
},
update: function() { console.log('update') },
delay: 30
});
$('#my_sortable li').click(function () {
if(!isSortableCalled){
console.log('click');
}
isSortableCalled = false;
});
The answer by mercilor worked for me a couple of caveats. The click event was actually on the handle element rather than the sorted item itself. Unfortunately the ui object, doesn't give you a reference to the handle in the update event (feature request to jquery ui?). So I had to get the handle myself. Also, I had to call preventDefault as well to stop the click action.
update: function(ev, ui) {
var handle = $(ui.item).find('h3');
handle.unbind("click");
handle.one("click", function (event) {
event.stopImmediatePropagation();
event.preventDefault();
$(this).click(clickHandler);
});
// other update code ...
Easier, use a var to know when the element is being sorted...
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.1/jquery-ui.min.js"></script>
<script type="text/javascript" charset="utf-8">
$().ready( function () {
$('#my_sortable').sortable({
start: function() {
sorting = true;
},
update: function() {
console.log('update');
sorting = false;
},
delay: 30
});
$('#my_sortable li').click(function () {
if (typeof(sorting) == "undefined" || !sorting) {
console.log('click');
}
});
});
</script>
<style type="text/css" media="screen">
#my_sortable li {
border: 1px solid black;
display: block;
width: 100px;
height: 100px;
background-color: gray;
}
</style>
</head>
<body>
<ul id="my_sortable">
<li id="item_1">A</li>
<li id="item_2">B</li>
<li id="item_3">C</li>
</ul>
</body>
</html>
Thanks to Elte Hupkus;
helper: 'clone'
I have implemented the same and a sample is shown below.
$(document).ready(function() {
$("#MenuListStyle").sortable({
helper:'clone',
revert:true
}).disableSelection();
});
One solution is to use live() instead of normal binding, but Elte Hupkes solution rocks!!!!
$('.menu_group tbody a').click(function(){
link = $(this).attr('href');
window.location.href = link;
});
This solution seems to be working for me. Now i can click on clickables inside sortable elements.
Note: ".menu_group tbody" is .sortable();

Categories

Resources