I am trying to implement isotope with pagination on my WordPress site (which obviously is a problem for most people). I've come up with a scenario which may work if I can figure a few things out.
On my page, I have this part of my isotope script -
$('.goforward').click(function(event) {
var href = $(this).attr('href');
$('.isotope').empty();
$('.isotope').load(href +".html .isotope > *");
$( 'div.box' ).addClass( 'isotope-item' );
$container.append( $items ).isotope( 'insert', $items, true );
event.preventDefault();
});
Then I am using this pagination function which I modified from here to have the 'goforward' class --
function isotope_pagination($pages = '', $range = 2)
{
$showitems = ($range * 2)+1;
global $paged;
if(empty($paged)) $paged = 1;
if($pages == '')
{
global $wp_query;
$pages = $wp_query->max_num_pages;
if(!$pages)
{
$pages = 1;
}
}
if(1 != $pages)
{
echo "<div class='pagination'>";
for ($i=1; $i <= $pages; $i++)
{
if (1 != $pages &&( !($i >= $paged+$range+1 || $i <= $paged-$range-1) || $pages <= $showitems ))
{
echo ($paged == $i)? "<a href='".get_pagenum_link($i)."' class='inactive goforward'>".$i."</a>":"<a href='".get_pagenum_link($i)."' class='inactive goforward' >".$i."</a>";
}
}
echo "</div>\n";
}
}
1st Problem - I'm having issues with the filtering/sorting. It filters fine for the first page, but doesn't sort. On the second page or any other page loaded it does not append/insert or even filter/sort when starting fresh on that page. Instead, when trying to do so it gives me this error --
Uncaught TypeError: Cannot read property '[object Array]' of undefined
2nd Problem - When loading the page fragments, there's a delay and the current page is still visible before the next page fragment is loaded in its place.
I know a lot of people have problems with isotope and pagination, usually, end up using infinite scroll even though isotope author does not recommend it.
So my theory is loading content via load() and have a callback of some sort to only display filtered items.
Any ideas on how to achieve this?
My entire isotope script ---
$(function () {
var selectChoice, updatePageState, updateFiltersFromObject,
$container = $('.isotope');
$items = $('.item');
////////////////////////////////////////////////////////////////////////////////////
/// EVENT HANDLERS
////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////
// Mark filtering element as active/inactive and trigger filters update
$('.js-filter').on( 'click', '[data-filter]', function (event) {
event.preventDefault();
selectChoice($(this), {click: true});
$container.trigger('filter-update');
});
//////////////////////////////////////////////////////
// Sort filtered (or not) elements
$('.js-sort').on('click', '[data-sort]', function (event) {
event.preventDefault();
selectChoice($(this), {click: true});
$container.trigger('filter-update');
});
//////////////////////////////////////////////////////
// Listen to filters update event and update Isotope filters based on the marked elements
$container.on('filter-update', function (event, opts) {
var filters, sorting, push;
opts = opts || {};
filters = $('.js-filter li.active a:not([data-filter="all"])').map(function () {
return $(this).data('filter');
}).toArray();
sorting = $('.js-sort li.active a').map(function () {
return $(this).data('sort');
}).toArray();
if (typeof opts.pushState == 'undefined' || opts.pushState) {
updatePageState(filters, sorting);
}
$container.isotope({
filter: filters.join(''),
sortBy: sorting
});
});
//////////////////////////////////////////////////////
// Set a handler for history state change
History.Adapter.bind(window, 'statechange', function () {
var state = History.getState();
updateFiltersFromObject(state.data);
$container.trigger('filter-update', {pushState: false});
});
////////////////////////////////////////////////////////////////////////////////////
/// HELPERS FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////
// Build an URI to get the query string to update the page history state
updatePageState = function (filters, sorting) {
var uri = new URI('');
$.each(filters, function (idx, filter) {
var match = /^\.([^-]+)-(.*)$/.exec(filter);
if (match && match.length == 3) {
uri.addSearch(match[1], match[2]);
}
});
$.each(sorting, function (idx, sort) {
uri.addSearch('sort', sort);
});
History.pushState(uri.search(true), null, uri.search() || '?');
};
//////////////////////////////////////////////////////
// Select the clicked (or from URL) choice in the dropdown menu
selectChoice = function ($link, opts) {
var $group = $link.closest('.btn-group'),
$li = $link.closest('li'),
mediumFilter = $group.length == 0;
if (mediumFilter) {
$group = $link.closest('.js-filter');
}
if (opts.click) {
$li.toggleClass('active');
} else {
$li.addClass('active');
}
$group.find('.active').not($li).removeClass('active');
if (!mediumFilter) {
if ($group.find('li.active').length == 0) {
$group.find('li:first-child').addClass('active');
}
$group.find('.selection').html($group.find('li.active a').first().html());
}
};
//////////////////////////////////////////////////////
// Update filters by the values in the current URL
updateFiltersFromObject = function (values) {
if ($.isEmptyObject(values)) {
$('.js-filter').each(function () {
selectChoice($(this).find('li').first(), {click: false});
});
selectChoice($('.js-sort').find('li').first(), {click: false});
} else {
$.each(values, function (key, val) {
val = typeof val == 'string' ? [val] : val;
$.each(val, function (idx, v) {
var $filter = $('[data-filter=".' + key + '-' + v + '"]'),
$sort = $('[data-sort="' + v + '"]');
if ($filter.length > 0) {
selectChoice($filter, {click: false});
} else if ($sort.length > 0) {
selectChoice($sort, {click: false});
}
});
});
}
};
////////////////////////////////////////////////////////////////////////////////////
/// Initialization
////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////
// Initialize Isotope
$container.imagesLoaded( function(){
$container.isotope({
masonry: { resizesContainer: true },
itemSelector: '.item',
getSortData: {
date: function ( itemElem ) {
var date = $( itemElem ).find('.thedate').text();
return parseInt( date.replace( /[\(\)]/g, '') );
},
area: function( itemElem ) { // function
var area = $( itemElem ).find('.thearea').text();
return parseInt( area.replace( /[\(\)]/g, '') );
},
price: function( itemElem ) { // function
var price = $( itemElem ).find('.theprice').text();
return parseInt( price.replace( /[\(\)]/g, '') );
}
}
});
var total = $(".next a:last").html();
var pgCount = 1;
var numPg = total;
pgCount++;
$('.goback').click(function() {
$('.isotope').empty();
$('.isotope').load("/page/<?php echo --$paged;?>/?<?php echo $_SERVER["QUERY_STRING"]; ?>.html .isotope > *");
$container.append( $items ).isotope( 'insert', $items, true );
$( 'div.box' ).addClass( 'isotope-item' );
});
$('.goforward').click(function(event) {
var href = $(this).attr('href');
$('.isotope').empty();
$('.isotope').load(href +".html .isotope > *");
$( 'div.box' ).addClass( 'isotope-item' );
$container.append( $items ).isotope( 'insert', $items, true );
event.preventDefault();
});
});
//////////////////////////////////////////////////////
// Initialize counters
$('.stat-count').each(function () {
var $count = $(this),
filter = $count.closest('[data-filter]').data('filter');
$count.html($(filter).length);
});
//////////////////////////////////////////////////////
// Set initial filters from URL
updateFiltersFromObject(new URI().search(true));
$container.trigger('filter-update', {pushState: false});
});
});
lazy loader works quite well,i've tried it myself
check codepen
you can also try:
var $container = $('#container').isotope({
itemSelector: itemSelector,
masonry: {
columnWidth: itemSelector,
isFitWidth: true
}
});
Have you checked the following link:
https://codepen.io/Igorxp5/pen/ojJLQE
It has a working example of isotope with pagination.
Have a look at the following block of code from the JS section:
var $container = $('#container').isotope({
itemSelector: itemSelector,
masonry: {
columnWidth: itemSelector,
isFitWidth: true
}
});
Check below link if usefull
https://mixitup.kunkalabs.com/extensions/pagination/
You can also use lazy loder for pagination.
Hope this'll help you
I think this will help you.
Refer this URL
Related
sorry for my english but i will try my best to ask my question correctly.
As layout i'm using this = https://codepen.io/Sool/pen/vvodgj with minor changes to support url hash.
Isotope JS Code:
$(document).ready(function($) {
var $grid = $('.grid').isotope({
// options
itemSelector: '.grid-item',
layoutMode: 'fitRows',
});
var filterFns = {
// show if number is greater than 50
numberGreaterThan50: function() {
var number = $(this).find('.number').text();
return parseInt(number, 10) > 50;
},
// show if name ends with -ium
ium: function() {
var name = $(this).find('.name').text();
return name.match(/ium$/);
}
};
function getHashFilter() {
// get filter=filterName
var matches = location.hash.match(/filter=([^&]+)/i);
var hashFilter = matches && matches[1];
return hashFilter && decodeURIComponent(hashFilter);
}
// change is-checked class on buttons
var $buttonGroup = $('.filters');
$buttonGroup.on('click', 'li', function(event) {
$buttonGroup.find('.is-checked').removeClass('is-checked');
var $button = $(event.currentTarget);
$button.addClass('is-checked');
var filterValue = $button.attr('data-filter');
// set filter in hash
location.hash = 'filter=' + encodeURIComponent(filterValue);
$grid.isotope({ filter: filterValue });
});
var isIsotopeInit = false;
function onHashchange() {
var hashFilter = getHashFilter();
if (!hashFilter && isIsotopeInit) {
return;
}
isIsotopeInit = true;
// filter isotope
$grid.isotope({
itemSelector: '.element-item',
layoutMode: 'fitRows',
// use filterFns
filter: filterFns[hashFilter] || hashFilter
});
// set selected class on button
if (hashFilter) {
$buttonGroup.find('.is-checked').removeClass('is-checked');
$buttonGroup.find('[data-filter="' + hashFilter + '"]').addClass('is-checked');
}
}
$(window).on('hashchange', onHashchange);
// trigger event handler to init Isotope
onHashchange();
})
AJAX Code:
$(document).ready(function() {
var limit = 7;
var start = 4;
var action = 'inactive';
function load_country_data(limit, start) {
$.ajax({
url: "fetch.php",
method: "POST",
data: { limit: limit, start: start },
cache: false,
success: function(data) {
$('#load_data').append(data);
if (data == '') {
$('#load_data_message').html("<button type='button'>All images loaded</button>");
action = 'active';
} else {
$('#load_data_message').html("<button type='button'>Loading images.....</button>");
action = "inactive";
}
}
});
}
if (action == 'inactive') {
action = 'active';
load_country_data(limit, start);
}
$(window).scroll(function() {
if ($(window).scrollTop() + $(document).height() > $("#load_data").height() && action == 'inactive') {
action = 'active';
start = start + limit;
setTimeout(function() {
load_country_data(limit, start);
}, 1000);
}
});
});
PHP Code to fetch data:
<?php
if(isset($_POST["limit"], $_POST["start"]))
{
include "mysqli_connection.php";
$query = "SELECT * FROM gallery ORDER BY order ASC LIMIT ".$_POST["start"].", ".$_POST["limit"]."";
$result = mysqli_query($conn, $query);
while ($row = mysqli_fetch_array($result)) {
?>
<div class="col-md-3 grid-item <?= htmlspecialchars($row["category"]) ?>" data-category="<?= htmlspecialchars($row["category"]) ?>">
<img data-src="/assets/images/gallery/<?= htmlspecialchars($row["image"]) ?>" data-srcset="/assets/images/gallery/<?= htmlspecialchars($row["image"]) ?>" class="img-fluid" alt="<?= htmlspecialchars($row["title"]) ?> Image" srcset="/assets/images/gallery/<?= htmlspecialchars($row["image"]) ?>" src="<?= htmlspecialchars($row["image"]) ?>">
</div>
<?php
}
mysqli_close($conn);
}
?>
The data is loaded from the database and everything seems to be fine. But at the same time, filtering stops working. How to make filtering work with ajax?
How to make sure that when you click on a certain category, data from a certain category is loaded? With ajax and working url hash, something like that domain.com/#filter=category1 or domain.com/#filter=category3.
I would be very grateful for any advice or help on this issue, thank you.
i tried to adapt the explanation from this post :
Lazy Load + Isotope
to my proper case :
http://40parallele.com/produits-test.php?id=4
but something is missing...
Here is my js code :
// Isotope
$j(window).load(function()
{
// lazyload
var $win = $(window);
var $imgs = $('img.lazy');
var $container = $j('#folio');
// calcul la taille des images
$imgs.each(function(index) {
var item_height = $(this).attr("height");
$(this).parent().parent().css("height",item_height);
});
if( $container.length )
{
$container.isotope(
{
itemSelector : '.folio-item'
});
var $optionSets = $j('#portfolio .folio-filter'),
$optionLinks = $optionSets.find('a');
$optionLinks.click(function()
{
var $this = $j(this);
// don't proceed if already selected
if ( $this.hasClass('selected') )
{
return false;
}
var $optionSet = $this.parents('.folio-filter');
$optionSet.find('.selected').removeClass('selected');
$this.addClass('selected');
// make option object dynamically, i.e. { filter: '.my-filter-class' }
var options = {},
key = $optionSet.attr('data-option-key'),
value = $this.attr('data-option-value');
// parse 'false' as false boolean
value = value === 'false' ? false : value;
options[ key ] = value;
if ( key === 'layoutMode' && typeof changeLayoutMode === 'function' )
{
changeLayoutMode( $this, options );
} else {
// otherwise, apply new options
$container.isotope( options );
}
return false;
});
}
$container.isotope({
onLayout: function() {
$win.trigger("scroll");
}
});
/*OK*/
$imgs.lazyload({
failure_limit: Math.max($imgs.length - 1, 0)
});
});
$j(window).bind('resize', function(e)
{
window.RT = setTimeout(function() {$j('#folio').isotope('reLayout'); }, 800);
});
thanks for your help
I have an issue, where I use jScroll for infinite scroll(jScroll), which works fine when the page loads. But the infinite scrolling is not working after an ajax call by a product filter in a search result page.
So here are my filter function called on change ajax call:
<script type='text/JavaScript'>
function filter_onchange()
{
$('#imgLoader').show();
$("#searchResults").load("<?php print $config_baseHREF; ?>search.php?ajax=1&"+$(".ajax").serialize());
$('imgLoader').hide();
}
</script>
Here is my jscroll script called from the footer.
<script>
$('.page-section').jscroll({
autotrigger: true,
loadingHtml: '<img class="center-block" src="/images/712.gif" alt="Loading" />',
padding: 20,
nextSelector: 'a.next',
contentSelector: '.infinite, .pagination',
});
</script>
So the issue is that after a user has used an filter(calling the function filter_onchange()) the jScroll stops working. In console I get the error:
TypeError: data is undefined
if (!data.waiting && iTotalHeight + _options.padding >= $inner.outerHeight()) {
jScroll.js
/*!
* jScroll - jQuery Plugin for Infinite Scrolling / Auto-Paging
* http://jscroll.com/
*
* Copyright 2011-2013, Philip Klauzinski
* http://klauzinski.com/
* Dual licensed under the MIT and GPL Version 2 licenses.
* http://jscroll.com/#license
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl-2.0.html
*
* #author Philip Klauzinski
* #version 2.3.4
* #requires jQuery v1.4.3+
* #preserve
*/
(function($) {
'use strict';
// Define the jscroll namespace and default settings
$.jscroll = {
defaults: {
debug: true,
autoTrigger: true,
autoTriggerUntil: false,
loadingHtml: '<small>Loading...</small>',
padding: 0,
nextSelector: 'a:last',
contentSelector: '',
pagingSelector: '',
callback: false
}
};
// Constructor
var jScroll = function($e, options) {
// Private vars and methods
var _data = $e.data('jscroll'),
_userOptions = (typeof options === 'function') ? { callback: options } : options,
_options = $.extend({}, $.jscroll.defaults, _userOptions, _data || {}),
_isWindow = ($e.css('overflow-y') === 'visible'),
_$next = $e.find(_options.nextSelector).first(),
_$window = $(window),
_$body = $('body'),
_$scroll = _isWindow ? _$window : $e,
_nextHref = $.trim(_$next.attr('href') + ' ' + _options.contentSelector),
// Check if a loading image is defined and preload
_preloadImage = function() {
var src = $(_options.loadingHtml).filter('img').attr('src');
if (src) {
var image = new Image();
image.src = src;
}
},
// Wrap inner content, if it isn't already
_wrapInnerContent = function() {
if (!$e.find('.jscroll-inner').length) {
$e.contents().wrapAll('<div class="jscroll-inner" />');
}
},
// Find the next link's parent, or add one, and hide it
_nextWrap = function($next) {
var $parent;
if (_options.pagingSelector) {
$next.closest(_options.pagingSelector).hide();
} else {
$parent = $next.parent().not('.jscroll-inner,.jscroll-added').addClass('jscroll-next-parent').hide();
if (!$parent.length) {
$next.wrap('<div class="jscroll-next-parent" />').parent().hide();
}
}
},
// Remove the jscroll behavior and data from an element
_destroy = function() {
return _$scroll.unbind('.jscroll')
.removeData('jscroll')
.find('.jscroll-inner').children().unwrap()
.filter('.jscroll-added').children().unwrap();
},
// Observe the scroll event for when to trigger the next load
_observe = function() {
_wrapInnerContent();
var $inner = $e.find('div.jscroll-inner').first(),
data = $e.data('jscroll'),
borderTopWidth = parseInt($e.css('borderTopWidth'), 10),
borderTopWidthInt = isNaN(borderTopWidth) ? 0 : borderTopWidth,
iContainerTop = parseInt($e.css('paddingTop'), 10) + borderTopWidthInt,
iTopHeight = _isWindow ? _$scroll.scrollTop() : $e.offset().top,
innerTop = $inner.length ? $inner.offset().top : 0,
iTotalHeight = Math.ceil(iTopHeight - innerTop + _$scroll.height() + iContainerTop);
if (!data.waiting && iTotalHeight + _options.padding >= $inner.outerHeight()) {
//data.nextHref = $.trim(data.nextHref + ' ' + _options.contentSelector);
_debug('info', 'jScroll:', $inner.outerHeight() - iTotalHeight, 'from bottom. Loading next request...');
return _load();
}
},
// Check if the href for the next set of content has been set
_checkNextHref = function(data) {
data = data || $e.data('jscroll');
if (!data || !data.nextHref) {
_debug('warn', 'jScroll: nextSelector not found - destroying');
_destroy();
return false;
} else {
_setBindings();
return true;
}
},
_setBindings = function() {
var $next = $e.find(_options.nextSelector).first();
if (!$next.length) {
return;
}
if (_options.autoTrigger && (_options.autoTriggerUntil === false || _options.autoTriggerUntil > 0)) {
_nextWrap($next);
if (_$body.height() <= _$window.height()) {
_observe();
}
_$scroll.unbind('.jscroll').bind('scroll.jscroll', function() {
return _observe();
});
if (_options.autoTriggerUntil > 0) {
_options.autoTriggerUntil--;
}
} else {
_$scroll.unbind('.jscroll');
$next.bind('click.jscroll', function() {
_nextWrap($next);
_load();
return false;
});
}
},
// Load the next set of content, if available
_load = function() {
var $inner = $e.find('div.jscroll-inner').first(),
data = $e.data('jscroll');
data.waiting = true;
$inner.append('<div class="jscroll-added" />')
.children('.jscroll-added').last()
.html('<div class="jscroll-loading">' + _options.loadingHtml + '</div>');
return $e.animate({scrollTop: $inner.outerHeight()}, 0, function() {
$inner.find('div.jscroll-added').last().load(data.nextHref, function(r, status) {
if (status === 'error') {
return _destroy();
}
var $next = $(this).find(_options.nextSelector).first();
data.waiting = false;
data.nextHref = $next.attr('href') ? $.trim($next.attr('href') + ' ' + _options.contentSelector) : false;
$('.jscroll-next-parent', $e).remove(); // Remove the previous next link now that we have a new one
_checkNextHref();
if (_options.callback) {
_options.callback.call(this);
}
_debug('dir', data);
});
});
},
// Safe console debug - http://klauzinski.com/javascript/safe-firebug-console-in-javascript
_debug = function(m) {
if (_options.debug && typeof console === 'object' && (typeof m === 'object' || typeof console[m] === 'function')) {
if (typeof m === 'object') {
var args = [];
for (var sMethod in m) {
if (typeof console[sMethod] === 'function') {
args = (m[sMethod].length) ? m[sMethod] : [m[sMethod]];
console[sMethod].apply(console, args);
} else {
console.log.apply(console, args);
}
}
} else {
console[m].apply(console, Array.prototype.slice.call(arguments, 1));
}
}
};
// Initialization
$e.data('jscroll', $.extend({}, _data, {initialized: true, waiting: false, nextHref: _nextHref}));
_wrapInnerContent();
_preloadImage();
_setBindings();
// Expose API methods via the jQuery.jscroll namespace, e.g. $('sel').jscroll.method()
$.extend($e.jscroll, {
destroy: _destroy
});
return $e;
};
// Define the jscroll plugin method and loop
$.fn.jscroll = function(m) {
return this.each(function() {
var $this = $(this),
data = $this.data('jscroll'), jscroll;
// Instantiate jScroll on this element if it hasn't been already
if (data && data.initialized) {
return;
}
jscroll = new jScroll($this, m);
});
};
})(jQuery);
Can anyone point me in the direction of what is wrong here - is it the placement of the scripts ?
In the filter ajax call, I do call the footer again so the jScroll script is part of the load in the filter function called.
I use the code below for sending ajax request to get more products on scroll down event. However it also sends ajax request when I scroll up, which is not intended. How can I modify it so that it will send a request only when I scroll it to the bottom?
_debug = true;
function dbg(msg) {
if (_debug) console.log(msg);
}
$(document).ready(function () {
$(".item-block img.lazy").lazyload({
effect: "fadeIn"
});
doMouseWheel = 1;
$("#result").append("<p id='last'></p>");
dbg("Document Ready");
var scrollFunction = function () {
dbg("Window Scroll Start");
/* if (!doMouseWheel) return;*/
var mostOfTheWayDown = ($('#last').offset().top - $('#result').height()) * 2 / 3;
dbg('mostOfTheWayDown html: ' + mostOfTheWayDown);
dbg('doMouseWheel html: ' + doMouseWheel);
if ($(window).scrollTop() >= mostOfTheWayDown) {
$(window).unbind("scroll");
dbg("Window distanceTop to scrollTop Start");
$('div#loadMoreComments').show();
doMouseWheel = 1;
dbg("Another window to the end !!!! " + $(".item-block:last").attr('id'));
$.ajax({
dataType: "html",
url: "search_load_more.php?lastComment=" + $(".item-block:last").attr('id') + "&" + window.location.search.substring(1),
success: function (html) {
doMouseWheel = 0;
if (html) {
$("#result").append(html);
dbg('Append html: ' + $(".item-block:first").attr('id'));
dbg('Append html: ' + $(".item-block:last").attr('id'));
$("#last").remove();
$("#result").append("<p id='last'></p>");
$('div#loadMoreComments').hide();
$("img.lazy").lazyload({
effect: "fadeIn"
});
$(window).scroll(scrollFunction);
} else {
//Disable Ajax when result from PHP-script is empty (no more DB-results )
$('div#loadMoreComments').replaceWith("<center><h1 style='color:red'>No more styles</h1></center>");
doMouseWheel = 0;
}
}
});
}
};
$(window).scroll(scrollFunction);
});
You'll need to detect the direction of the scroll and add that as a boolean check. This post covers it.
The snippet they provide:
var lastScrollTop = 0;
$(window).scroll(function(event){
var st = $(this).scrollTop();
if (st > lastScrollTop){
// downscroll code
} else {
// upscroll code
}
lastScrollTop = st;
});
So you'll probably do something like:
$(window).scrollTop() >= mostOfTheWayDown && st > lastScrollTop
I have changed the below line
if ($(window).scrollTop() >= mostOfTheWayDown)
to
if( $(window).height() + $(window).scrollTop() == $(document).height())
this worked for me. Hope this can help others too. Thanks
I am having trouble sending data to the database. The values are being sent, but they are all going into the first drop zone field. And I need each dropzone value to go into the correct field in the database.
I've tried putting in different listeners & if statements in the javascript but it won't work for me.
the html:
<ul id="images">
<li><a id="img1" draggable="true"><img src="images/1.jpg"></a></li>
<li><a id="img2" draggable="true"><img src="images/2.jpg"></a></li>
<li><a id="img3" draggable="true"><img src="images/3.jpg"></a></li>
</ul>
//dropzones
<div class="drop_zones">
<div class="drop_zone" id="drop_zone1" droppable="true">
</div>
<div class="drop_zone" id="drop_zone2" droppable="true">
</div>
<div class="drop_zone" id="drop_zone3" droppable="true">
</div>
</div>
<button id = "post" onClick="postdb();">Post info</button>
the javascript:
var addEvent = (function () {
if (document.addEventListener) {
return function (el, type, fn) {
if (el && el.nodeName || el === window) {
el.addEventListener(type, fn, false);
} else if (el && el.length) {
for (var i = 0; i < el.length; i++) {
addEvent(el[i], type, fn);
}
}
};
} else {
return function (el, type, fn) {
if (el && el.nodeName || el === window) {
el.attachEvent('on' + type, function () {
return fn.call(el, window.event);
});
} else if (el && el.length) {
for (var i = 0; i < el.length; i++) {
addEvent(el[i], type, fn);
}
}
};
}
})();
var dragItems;
updateDataTransfer();
var dropAreas = document.querySelectorAll('[droppable=true]');
function cancel(e) {
if (e.preventDefault) {
e.preventDefault();
}
return false;
}
function updateDataTransfer() {
dragItems = document.querySelectorAll('[draggable=true]');
for (var i = 0; i < dragItems.length; i++) {
addEvent(dragItems[i], 'dragstart', function (event) {
event.dataTransfer.setData('obj_id', this.id);
return false;
});
}
}
addEvent(dropAreas, 'dragover', function (event) {
if (event.preventDefault)
event.preventDefault();
this.style.borderColor = "#000";
return false;
});
addEvent(dropAreas, 'dragleave', function (event) {
if (event.preventDefault)
event.preventDefault();
this.style.borderColor = "#ccc";
return false;
});
addEvent(dropAreas, 'dragenter', cancel);
// drop event handler
addEvent(dropAreas, 'drop', function (event) {
if (event.preventDefault)
event.preventDefault();
// get dropped object
var iObj = event.dataTransfer.getData('obj_id');
var oldObj = document.getElementById(iObj);
// get its image src
var oldSrc = oldObj.childNodes[0].src;
oldObj.className += 'hidden';
var oldThis = this;
setTimeout(function () {
oldObj.parentNode.removeChild(oldObj); // remove object from DOM
// add similar object in another place
oldThis.innerHTML += '<a id="' + iObj + '" draggable="true"><img src="' + oldSrc + '" /> </a>';
// and update event handlers
updateDataTransfer();
function postdb(){
if (document.querySelectorAll('[droppable=true]')){
var dropDetails = oldThis.id + '=' + iObj;
$.post("a-2.php", dropDetails);
}
oldThis.style.borderColor = "#ccc";
}, 500);
return false;
});
and my php:
$sql="INSERT INTO table_answers (drop_zone1, drop_zone2, drop_zone3) VALUES ('$_POST[drop_zone1]','$_POST[drop_zone2]','$_POST[drop_zone3]')";
Any idea please?
var u = $('drop_zone1');
if(u){
$.post("post.php", y);
};
(I'm assuming this is jQuery.)
Add the # to the beginning of the selector: $('#drop_zone1');.
The jQuery resultset always evaluates to a truthy value. It's not clear to me what condition you're trying to validate here...
In the PHP code, you're creating the query in $sql2 in the first if, as opposed to $sql in the other two.
Edit - now that we know what you're trying to do in setTimeout, this simplified function should work:
setTimeout(function() {
oldObj.parentNode.removeChild(oldObj); // remove object from DOM
// add similar object in another place
oldThis.innerHTML += '<a id="' + iObj + '" draggable="true"><img src="' + oldSrc + '" /> </a>';
// and update event handlers
updateDataTransfer();
/*
this part has been removed, see edit below
var dropDetails = oldThis.id + '=' + iObj;
// now dropDetails should look something like "drop_zone1=img1"
$.post("post.php", dropDetails);
*/
oldThis.style.borderColor = "#ccc";
}, 500);
One more edit, to submit all the dropped elements at once:
function postdb() {
var postDetails = {};
var dropZones = document.querySelectorAll('[droppable=true]');
var allZonesDropped = true;
for(var ix = 0; ix < dropZones.length; ++ix) {
var zone = dropZones[ix];
var dropped = zone.querySelector('[draggable=true]');
if(dropped) {
var dropTag = dropped.id;
postDetails[zone.id] = dropTag;
} else {
allZonesDropped = false;
}
}
if(allZonesDropped) {
$.post("a-2.php", dropDetails);
} else {
alert('Not all targets have elements in them');
}
return false;
});
Just be careful where you place this function - your edited question has it in the middle of the setTimeout call, where it's definitely not going to work.
Regarding your PHP code: You should really learn about PDO or MySQLi and use prepared statements instead of blindly inserting user input into the query. If you care to learn, here is a quite good PDO-related tutorial.