Matching drag'n'drop elements - javascript

I am trying to understand the drag and drop mechanics in JS and HTML. I have used some code I have found and am trying to adapt it into something different. I want the cardPile to include pictures, with names such as "motherboard.jpg" etc, and match it to the cardSlots with similar names. How could I do that? I tried changing the numeric values in cardPile into strings, but it does not work with dropping.
Any advice? (Sorry, it is my first time on StackOverflow :') )
JS code:
var correctCards = 0;
$( init );
function init() {
// Hide the success message
$('#successMessage').hide();
$('#successMessage').css( {
left: '580px',
top: '250px',
width: 0,
height: 0
} );
// Reset the game
correctCards = 0;
$('#cardPile').html( '' );
$('#cardSlots').html( '' );
// Create the pile of shuffled cards
var numbers = [ 1, "a", "b", "c", "d", "e", "f", "g", "h", "i" ];
numbers.sort( function() { return Math.random() - .5 } );
for ( var i=0; i<10; i++ ) {
$('<div>' + numbers[i] + '</div>').data( 'number', numbers[i] ).attr( 'id', 'card'+numbers[i] ).appendTo( '#cardPile' ).draggable( {
containment: '#content',
stack: '#cardPile div',
cursor: 'move',
revert: true
} );
}
// Create the card slots
var words = [ 'Motherboard', 'RAM', 'GPU', 'CPU', 'I/O', 'Power supply', 'Oprical Drive', 'HDD', 'SSD', 'Expansion slots' ];
for ( var i=1; i<=10; i++ ) {
$('<div>' + words[i-1] + '</div>').data( 'number', i ).appendTo( '#cardSlots' ).droppable( {
accept: '#cardPile div',
hoverClass: 'hovered',
drop: handleCardDrop
} );
}
}
function handleCardDrop( event, ui ) {
var slotNumber = $(this).data( 'number' );
var cardNumber = ui.draggable.data( 'number' );
// If the card was dropped to the correct slot,
// change the card colour, position it directly
// on top of the slot, and prevent it being dragged
// again
if ( slotNumber == cardNumber ) {
ui.draggable.addClass( 'correct' );
ui.draggable.draggable( 'disable' );
$(this).droppable( 'disable' );
ui.draggable.position( { of: $(this), my: 'left top', at: 'left top' } );
ui.draggable.draggable( 'option', 'revert', false );
correctCards++;
}
// If all the cards have been placed correctly then display a message
// and reset the cards for another go
if ( correctCards == 10 ) {
$('#successMessage').show();
$('#successMessage').animate( {
left: '380px',
top: '200px',
width: '400px',
height: '100px',
opacity: 1
} );
}
}

Related

How to fix Range on jQuery-UI slider and trigger function on hange

I have a basic form that calculates an estimated price based on quantity and one of three options. Then I tried to add a jQuery-UI slider. I need the slider to use the same values as the SELECT, in this case 10-100 but instead it seems to be using 19-109. This means I can't select the lowest value at all without using the SELECT and the max is right off the scale. I also need it to trigger my setAmount() function on slider change to update the price. I thought these would be easy to resolve but I'm still learning. I've included a jsfiddle and would be very appreciative if anyone could point me in the right direction.
Current Code:
<script type='text/javascript'>
$(document).ready(function(){
var select = $( "#quantity" );
var slider = $( "<div id='slider'></div>" ).insertAfter( select ).slider({
min: 10,
max: 100,
range: "min",
value: select[ 0 ].selectedIndex + 1,
slide: function( event, ui ) {
select[ 0 ].selectedIndex = ui.value - 1;
}
});
$( "#quantity" ).on( "change", function() {
slider.slider( "value", this.selectedIndex + 1 );
});
$('.containing-element').children().on("change", function () {setAmount();});
$("#quantity").on("change", function () {setAmount();});
});
</script>
https://jsfiddle.net/Bestrafung/2cwp9ud6/1
I believe you are getting incorrect behavior by using the selectedIndex from the #quantity select.
$(document).ready(function(){
var select = $( "#quantity" );
var slider = $( "<div id='slider'></div>" ).insertAfter( select ).slider({
range: "min",
value: 10,
min: 10,
max: 100,
slide: function( event, ui ) {
select.val( ui.value );
},
change: function(event, ui){
setAmount();
}
});
$('.containing-element').children().on("change", function () {
setAmount();
});
select.on("change", function () {
setAmount();
slider.slider( "value", select.val() );
});
function setAmount(){
var a = select.val();
if (a <= 10){var q = 9.50}
else if (a > 10 && a <= 20){var q = 7.5}
else if (a > 20 && a <= 50){var q = 4.25}
else if (a > 50 && a <= 100){var q = 2.50}
if ($("#flip-min").val() == "noback") {$("#amount").val((a*q).toFixed(2));}
if ($("#flip-min").val() == "hookback") {$("#amount").val((a*(q+.5)).toFixed(2));}
if ($("#flip-min").val() == "stickyback") {$("#amount").val((a*(q+.6)).toFixed(2));}
}
});
This should correct the behavior by using ui.value and modifying the select.

Make a slider responsive (jQuery)

I have a slider, I want to make them responsive the problem is the size of slider is into the jQuery file
sow how I can edit the code ?
code of jQuery
(function( window, $, undefined ) {
var $event = $.event, resizeTimeout;
$event.special.smartresize = {
setup: function() {
$(this).bind( "resize", $event.special.smartresize.handler );
},
teardown: function() {
$(this).unbind( "resize", $event.special.smartresize.handler );
},
handler: function( event, execAsap ) {
// Save the context
var context = this,
args = arguments;
// set correct event type
event.type = "smartresize";
if ( resizeTimeout ) { clearTimeout( resizeTimeout ); }
resizeTimeout = setTimeout(function() {
jQuery.event.handle.apply( context, args );
}, execAsap === "execAsap"? 0 : 100 );
}
};
$.fn.smartresize = function( fn ) {
return fn ? this.bind( "smartresize", fn ) : this.trigger( "smartresize", ["execAsap"] );
};
$.Slideshow = function( options, element ) {
this.$el = $( element );
/***** images ****/
// list of image items
this.$list = this.$el.find('ul.ei-slider-large');
// image items
this.$imgItems = this.$list.children('li');
// total number of items
this.itemsCount = this.$imgItems.length;
// images
this.$images = this.$imgItems.find('img:first');
/***** thumbs ****/
// thumbs wrapper
this.$sliderthumbs = this.$el.find('ul.ei-slider-thumbs').hide();
// slider elements
this.$sliderElems = this.$sliderthumbs.children('li');
// sliding div
this.$sliderElem = this.$sliderthumbs.children('li.ei-slider-element');
// thumbs
this.$thumbs = this.$sliderElems.not('.ei-slider-element');
// initialize slideshow
this._init( options );
};
$.Slideshow.defaults = {
// animation types:
// "sides" : new slides will slide in from left / right
// "center": new slides will appear in the center
animation : 'center', // sides || center
// if true the slider will automatically slide, and it will only stop if the user clicks on a thumb
autoplay : false,
// interval for the slideshow
slideshow_interval : 3000,
// speed for the sliding animation
speed : 800,
// easing for the sliding animation
easing : '',
// percentage of speed for the titles animation. Speed will be speed * titlesFactor
titlesFactor : 0.60,
// titles animation speed
titlespeed : 800,
// titles animation easing
titleeasing : '',
};
$.Slideshow.prototype = {
_init : function( options ) {
this.options = $.extend( true, {}, $.Slideshow.defaults, options );
// set the opacity of the title elements and the image items
this.$imgItems.css( 'opacity', 0 );
this.$imgItems.find('div.ei-title > *').css( 'opacity', 0 );
// index of current visible slider
this.current = 0;
var _self = this;
// preload images
// add loading status
this.$loading = $('<div class="ei-slider-loading">Loading</div>').prependTo( _self.$el );
$.when( this._preloadImages() ).done( function() {
// hide loading status
_self.$loading.hide();
// calculate size and position for each image
_self._setImagesSize();
// configure thumbs container
_self._initThumbs();
// show first
_self.$imgItems.eq( _self.current ).css({
'opacity' : 1,
'z-index' : 10
}).show().find('div.ei-title > *').css( 'opacity', 1 );
// if autoplay is true
if( _self.options.autoplay ) {
_self._startSlideshow();
}
// initialize the events
_self._initEvents();
});
},
_preloadImages : function() {
// preloads all the large images
var _self = this,
loaded = 0;
return $.Deferred(
function(dfd) {
_self.$images.each( function( i ) {
$('<img/>').load( function() {
if( ++loaded === _self.itemsCount ) {
dfd.resolve();
}
}).attr( 'src', $(this).attr('src') );
});
}
).promise();
},
_setImagesSize : function() {
// save ei-slider's width
this.elWidth = this.$el.width();
var _self = this;
this.$images.each( function( i ) {
var $img = $(this);
imgDim = _self._getImageDim( $img.attr('src') );
$img.css({
width : imgDim.width,
height : imgDim.height,
marginLeft : imgDim.left,
marginTop : imgDim.top
});
});
},
_getImageDim : function( src ) {
var $img = new Image();
$img.src = src;
var c_w = this.elWidth,
c_h = this.$el.height(),
r_w = c_h / c_w,
i_w = $img.width,
i_h = $img.height,
r_i = i_h / i_w,
new_w, new_h, new_left, new_top;
if( r_w > r_i ) {
new_h = c_h;
new_w = c_h / r_i;
}
else {
new_h = c_w * r_i;
new_w = c_w;
}
return {
width : new_w,
height : new_h,
left : ( c_w - new_w ) / 2,
top : ( c_h - new_h ) / 2
};
},
_initThumbs : function() {
// set the max-width of the slider elements to the one set in the plugin's options
// also, the width of each slider element will be 100% / total number of elements
this.$sliderElems.css({
'width' : 100 / this.itemsCount + '%'
});
// set the max-width of the slider and show it
this.$sliderthumbs.css( 'width', this.options.thumbMaxWidth * this.itemsCount + 'px' ).show();
},
_startSlideshow : function() {
var _self = this;
this.slideshow = setTimeout( function() {
var pos;
( _self.current === _self.itemsCount - 1 ) ? pos = 0 : pos = _self.current + 1;
_self._slideTo( pos );
if( _self.options.autoplay ) {
_self._startSlideshow();
}
}, this.options.slideshow_interval);
},
// shows the clicked thumb's slide
_slideTo : function( pos ) {
// return if clicking the same element or if currently animating
if( pos === this.current || this.isAnimating )
return false;
this.isAnimating = true;
var $currentSlide = this.$imgItems.eq( this.current ),
$nextSlide = this.$imgItems.eq( pos ),
_self = this,
preCSS = {zIndex : 10},
animCSS = {opacity : 1};
// new slide will slide in from left or right side
if( this.options.animation === 'sides' ) {
preCSS.left = ( pos > this.current ) ? -1 * this.elWidth : this.elWidth;
animCSS.left = 0;
}
// titles animation
$nextSlide.find('div.ei-title > h2')
.css( 'margin-right', 50 + 'px' )
.stop()
.delay( this.options.speed * this.options.titlesFactor )
.animate({ marginRight : 0 + 'px', opacity : 1 }, this.options.titlespeed, this.options.titleeasing )
.end()
.find('div.ei-title > h3')
.css( 'margin-right', -50 + 'px' )
.stop()
.delay( this.options.speed * this.options.titlesFactor )
.animate({ marginRight : 0 + 'px', opacity : 1 }, this.options.titlespeed, this.options.titleeasing )
$.when(
// fade out current titles
$currentSlide.css( 'z-index' , 1 ).find('div.ei-title > *').stop().fadeOut( this.options.speed / 2, function() {
// reset style
$(this).show().css( 'opacity', 0 );
}),
// animate next slide in
$nextSlide.css( preCSS ).stop().animate( animCSS, this.options.speed, this.options.easing ),
// "sliding div" moves to new position
this.$sliderElem.stop().animate({
left : this.$thumbs.eq( pos ).position().left
}, this.options.speed )
).done( function() {
// reset values
$currentSlide.css( 'opacity' , 0 ).find('div.ei-title > *').css( 'opacity', 0 );
_self.current = pos;
_self.isAnimating = false;
});
},
_initEvents : function() {
var _self = this;
// window resize
$(window).on( 'smartresize.eislideshow', function( event ) {
// resize the images
_self._setImagesSize();
// reset position of thumbs sliding div
_self.$sliderElem.css( 'left', _self.$thumbs.eq( _self.current ).position().left );
});
// click the thumbs
this.$thumbs.on( 'click.eislideshow', function( event ) {
if( _self.options.autoplay ) {
clearTimeout( _self.slideshow );
_self.options.autoplay = false;
}
var $thumb = $(this),
idx = $thumb.index() - 1; // exclude sliding div
_self._slideTo( idx );
return false;
});
}
};
var logError = function( message ) {
if ( this.console ) {
console.error( message );
}
};
$.fn.eislideshow = function( options ) {
if ( typeof options === 'string' ) {
var args = Array.prototype.slice.call( arguments, 1 );
this.each(function() {
var instance = $.data( this, 'eislideshow' );
if ( !instance ) {
logError( "cannot call methods on eislideshow prior to initialization; " +
"attempted to call method '" + options + "'" );
return;
}
if ( !$.isFunction( instance[options] ) || options.charAt(0) === "_" ) {
logError( "no such method '" + options + "' for eislideshow instance" );
return;
}
instance[ options ].apply( instance, args );
});
}
else {
this.each(function() {
var instance = $.data( this, 'eislideshow' );
if ( !instance ) {
$.data( this, 'eislideshow', new $.Slideshow( options, this ) );
}
});
}
return this;
};
})( window, jQuery );
How I can edit that to make them responsive ? can you give an example ?
I suggest you use something more simple (only 3 steps) instead of review this code.
Code:
Step 1: Link required files
First and most important, the jQuery library needs to be included (no need to download - link directly from Google). Next, download the package from this site and link the bxSlider CSS file (for the theme) and the bxSlider Javascript file.
<!-- jQuery library (served from Google) -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<!-- bxSlider Javascript file -->
<script src="/js/jquery.bxslider.min.js"></script>
<!-- bxSlider CSS file -->
<link href="/lib/jquery.bxslider.css" rel="stylesheet" />
Step 2: Create HTML markup
Create a <ul class="bxslider"> element, with a <li> for each slide. Slides can contain images, video, or any other HTML content!
<ul class="bxslider">
<li><img src="/images/pic1.jpg" /></li>
<li><img src="/images/pic2.jpg" /></li>
<li><img src="/images/pic3.jpg" /></li>
<li><img src="/images/pic4.jpg" /></li>
</ul>
Step 3: Call the bxSlider
Call .bxslider() on <ul class="bxslider">. Note that the call must be made inside of a $(document).ready() call, or the plugin will not work!
$(document).ready(function(){
$('.bxslider').bxSlider();
});
I really believe, this will be more helpful and simple.
Credits: http://bxslider.com
Different configurations
$('.bxslider').bxSlider({
mode: 'fade',
captions: true,
pagerCustom: '#bx-pager',
adaptiveHeight: true,
slideWidth: 150
});
Don't forget to read this: http://bxslider.com/options

Multiple (but not all) card slots

Trying to recreate a game in which cards are sorted into card slots. I can make it so that card 'a' goes into the first card slot 'Even', but I want to make it so that card 'a' can also go in the the second card slot 'Even.' Similarly, I want card 'b' to be able to go into either 'Even' slot. Ditto cards 'c' and 'd' for either 'Odd' slot and 'e' and 'f' for the either 'Even and Odd' slots. Any ideas?
// Create the pile of shuffled cards
var equations = [];
equations [ 0 ] = {x:1, y:'a'};
equations [ 1 ] = {x:2, y:'b'};
equations [ 2 ] = {x:3, y:'c'};
equations [ 3 ] = {x:4, y:'d'};
equations [ 4 ] = {x:5, y:'e'};
equations [ 5 ] = {x:6, y:'f'};
equations.sort( function() { return Math.random() - .4 } );
for ( var i=0; i<6; i++ ) {
$('<div>' + equations[i].y + '</div>').data( 'number', equations[i].x ).attr( 'id', 'card'+equations[i].x ).appendTo( '#cardPile' ).draggable( {
containment: '#content',
stack: '#cardPile div',
cursor: 'move',
revert: true
} );
}
// Create the card slots
var words = [ 'Even', 'Even', 'Odd)', 'Odd', 'Even + Odd', 'Even + Odd' ];
for ( var i=1; i<=6; i++ ) {
$('<div>' + words[i-1] + '</div>').data( 'number', i ).appendTo( '#cardSlots' ).droppable( {
accept: '#cardPile div',
hoverClass: 'hovered',
drop: handleCardDrop
} );
}
}
function handleCardDrop( event, ui ) {
var slotNumber = $(this).data( 'number' );
var cardNumber = ui.draggable.data( 'number' );
// If the card was dropped to the correct slot,
// change the card colour, position it directly
// on top of the slot, and prevent it being dragged
// again
if ( slotNumber == cardNumber) {
ui.draggable.addClass( 'correct' );
ui.draggable.draggable( 'disable' );
$(this).droppable( 'disable' );
ui.draggable.position( { of: $(this), my: 'left top', at: 'left top' } );
ui.draggable.draggable( 'option', 'revert', false );
correctCards++;
}
// If all the cards have been placed correctly then display a message
// and reset the cards for another go
if ( correctCards == 6) {
$('#successMessage').show();
$('#successMessage').animate( {
left: '430px',
top: '150px',
width: '400px',
height: '180px',
opacity: 1
} );
}
}
});
Right now you have a one-to-one relationship between cards and slots, but it sounds like you want a one-to-many relationship.
So first thing you need to do is define the correct answer for each of your equations by adding a third value.
equations [ 0 ] = {x:1, y:'a', correct: 'Even'};
(You can make this an array if you want multiple correct answers.)
Next, you need to add this answer to the card's data.
.data( 'correct', equations[i].correct )
And finally check for the answer when you handle the drop
var slotAnswer = $(this).text();
var cardAnswer = ui.draggable.data( 'correct' );
if ( slotAnswer == cardAnswer) {
It might be better to store the slot answer in the data instead of just the text.
Also, you have a typo in the slot name of Odd)

Draggable object doesn't recognize target Javascript Jquery

I'm new to Javascript, but I customized a code from an array of number to an array of letters in which I want to recognize the target in order to complete the game.
The error in the code is that its drops to any of the targets, that means that it doesn't recognize the respectively target.
The original code
and the code that I customized.
var correctCards = 0;
$(init);
function init() {
// Hide the success message
$('#successMessage').hide();
$('#successMessage').css({
left: '580px',
top: '250px',
width: 0,
height: 0
});
// Reset the game
correctCards = 0;
$('#vocalPile').html('');
$('#vocalSlots').html('');
// Create the pile of shuffled cards
var vocales = ["a", 'e','i' , 'o', 'u'];
vocales.sort( function() { return Math.random() - .5 } );
for ( var i=0; i<5; i++ ) {
$('<div>' + vocales[i] + '</div>')
.data('vocal', vocales[i])
.attr('id', 'vocal'+vocales[i])
.appendTo('#vocalPile')
.draggable({
containment: '#content',
stack: '#vocalPile div',
cursor: 'move',
revert: true
});
}
// Create the card slots
var words = ['a', 'e', 'i', 'o', 'u'];
for (var i = 1; i <= 5; i++ ) {
$('<div>' + words[i-1] + '</div>')
.data('vocal', i)
.appendTo('#vocalSlots')
.droppable({
accept: '#vocalPile div',
hoverClass: 'hovered',
drop: handleCardDrop
});
}
}
function handleCardDrop( event, ui ) {
var slotVocal = $(this).data('vocales');
var cardVocal = ui.draggable.data('vocales');
// If the card was dropped to the correct slot,
// change the card colour, position it directly
// on top of the slot, and prevent it being dragged
// again
if ( slotVocal == cardVocal ) {
ui.draggable.addClass('correct');
ui.draggable.draggable('disable');
$(this).droppable('disable');
ui.draggable.position({ of: $(this), my: 'left top', at: 'left top' });
ui.draggable.draggable('option', 'revert', false);
correctCards++;
}
// If all the cards have been placed correctly then display a message
// and reset the cards for another go
if (correctCards == 5) {
$('#successMessage').show();
$('#successMessage').animate( {
left: '380px',
top: '200px',
width: '400px',
height: '100px',
opacity: 1
});
}
}
I think that there's an error in the parameters that is passing through the functions. But I dont know how to change them in the if ==.
Thanks :)
PS. Is an array of vowels not number the one that I want to implement.
You have an error in
in create card slots:
$('<div>' + words[i-1] + '</div>')
.data( 'vocal',words[i-1])...
use words array
in handleCardDrop function fix data attribute to vocal not vocales as in your fiddle
function handleCardDrop( event, ui ) {
var slotVocal = $(this).data( 'vocal' );
var cardVocal = ui.draggable.data( 'vocal' );
working fiddle

Autoscrolling slide javascript

I have This javascript code for a slider that I downloaded , and can't figure out how to make it auto scrolling !!
I actually downloaded this code from http://tympanus.net/Tutorials/FullscreenSlitSlider/index2.html
It actually don't contain a next button so i can add an interval like the other sliders :(
$(function() {
var Page = (function() {
var $nav = $( '#nav-dots > span' ),
slitslider = $( '#slider' ).slitslider( {
onBeforeChange : function( slide, pos ) {
$nav.removeClass( 'nav-dot-current' );
$nav.eq( pos ).addClass( 'nav-dot-current' );
}
} ),
init = function() {
initEvents();
setInterval(initEvents,1000);
},
initEvents = function() {
$nav.each( function( i ) {
$( this ).on( 'click', function( event ) {
var $dot = $( this );
if( !slitslider.isActive() ) {
$nav.removeClass( 'nav-dot-current' );
$dot.addClass( 'nav-dot-current' );
}
slitslider.jump( i + 1 );
return false;
} );
} );
};
return { init : init };
})();
Page.init();
});
Like it says in the docs (Google is helpful):
slitslider = $( '#slider' ).slitslider({
autoplay : true
});
should do it.
If you don't want to read the whole thing, here's a short list of common config options:
$.Slitslider.defaults = {
// transitions speed
speed : 800,
// if true the item's slices will also animate the opacity value
optOpacity : false,
// amount (%) to translate both slices - adjust as necessary
translateFactor : 230,
// maximum possible angle
maxAngle : 25,
// maximum possible scale
maxScale : 2,
// slideshow on / off
autoplay : false,
// keyboard navigation
keyboard : true,
// time between transitions
interval : 4000,
// callbacks
onBeforeChange : function( slide, idx ) { return false; },
onAfterChange : function( slide, idx ) { return false; }
};

Categories

Resources