Reload script (Poptrox) after ajax request - javascript

So I'm using an AJAX request to load data from the database into a DIV. At the same time, I'm using the same data inside the DIV in a different script (Poptrox) witch does some design stuff.
Without the AJAX request, poptrox works, but if I'm using it together with poptrox it doesn't do the designing anymore.
Is there a way to reload the poptrox-script after the ajax request?
NOTE: the AJAX-Code and the Poptrox-code are placed inside the "main.js"!
Thanks in advance!
php:
<script src="assets/js/jquery.min.js"></script>
<section class="wrapper">
<form action="kochbuch.html" method="get" id="searchfilter">
<input type="text" class="searchBox" name="searchBox" id="searchBox" placeholder="Search..">
<button type="submit" id="searchBtn"><i class="fas fa-search"></i></button>
</form>
</section>
<section class="wrapper">
<div id="gerichte"></div>
</section>
<script src="assets/js/main.js"></script>
js-ajax:
var queryString = window.location.search;
var urlParams = new URLSearchParams(queryString);
if (urlParams.has('searchBox')){
var searchBox = urlParams.get('searchBox');
$.ajax({
type: "POST",
url: "kochbuch/fetchdata.php",
data: {
"search_post_btn": 1,
"searchBox": searchBox,
},
dataType: "json",
success: function (response) {
$("#gerichte").html(response);
}
});
};
js-poptrox:
// Gerichte.
var $gerichte = $('#gerichte');
// Thumbs.
$gerichte.children('.thumb').each(function() {
var $this = $(this),
$image = $this.find('.image'), $image_img = $image.children('img'),
x;
// No image? Bail.
if ($image.length == 0)
return;
// Image.
// This sets the background of the "image" <span> to the image pointed to by its child
// <img> (which is then hidden). Gives us way more flexibility.
// Set background.
$image.css('background-image', 'url(' + $image_img.attr('src') + ')');
// Set background position.
if (x = $image_img.data('position'))
$image.css('background-position', x);
// Hide original img.
$image_img.hide();
});
// Poptrox.
$gerichte.poptrox({
baseZIndex: 20000,
caption: function($a) {
var s = '';
$a.nextAll().each(function() {
s += this.outerHTML;
});
return s;
},
fadeSpeed: 300,
onPopupClose: function() { $body.removeClass('modal-active'); },
onPopupOpen: function() { $body.addClass('modal-active'); },
overlayOpacity: 0,
popupCloserText: '',
popupHeight: 150,
popupLoaderText: '',
popupSpeed: 300,
popupWidth: 150,
selector: '.thumb > a.image',
usePopupCaption: true,
usePopupCloser: true,
usePopupDefaultStyling: false,
usePopupForceClose: true,
usePopupLoader: true,
usePopupNav: true,
windowMargin: 50
});
// Hack: Set margins to 0 when 'xsmall' activates.
breakpoints.on('<=xsmall', function() {
$main[0]._poptrox.windowMargin = 0;
});
breakpoints.on('>xsmall', function() {
$main[0]._poptrox.windowMargin = 50;
});

alright, i found one possible solution, but know the preloaded data ist formated:
the whole poptrox code has to be wrapped by this function:
$(document).ajaxStop(function () {
// function after ajax
});
If you know any better solution, feel free to submit :)
EDIT:
alright, my solution was as follows:
if (urlParams.has('searchBox')){
var searchBox = urlParams.get('searchBox');
} else {
var searchBox = '';
}
$.ajax({ .....

Related

Change Dropzone maxFiles Dynamically

I'm trying to dynamically update the MaxFiles property each time a new image is uploaded/deleted.
By using the following code its not allowing any image to upload instead of limitize it to maxFiles. And it is not taking the value of the variable maxFile, but when i remove maxFile variable And put a number then it works fine.
got source code idea from this Answer.
!function ($) {
"use strict";
var Onyx = Onyx || {};
Onyx = {
init: function() {
var self = this,
obj;
for (obj in self) {
if ( self.hasOwnProperty(obj)) {
var _method = self[obj];
if ( _method.selector !== undefined && _method.init !== undefined ) {
if ( $(_method.selector).length > 0 ) {
_method.init();
}
}
}
}
},
userFilesDropzone: {
selector: 'form.dropzone',
init: function() {
var base = this,
container = $(base.selector);
base.initFileUploader(base, 'form.dropzone');
},
initFileUploader: function(base, target) {
var maxFile = $('.dropzone').attr('data-count');
var onyxDropzone = new Dropzone(target, {
url: ($(target).attr("action")) ? $(target).attr("action") : "data.php", // Check that our form has an action attr and if not, set one here
maxFiles: maxFile,
maxFilesize: 5,
acceptedFiles: ".JPG,.PNG,.JPEG",
// previewTemplate: previewTemplate,
// previewsContainer: "#previews",
clickable: true,
uploadMultiple: false,
});
onyxDropzone.on("success", function(file, response) {
let parsedResponse = JSON.parse(response);
file.upload_ticket = parsedResponse.file_link;
var imagecount = $('.dropzone').attr('data-count');
imagecount = imagecount - 1;
$('.dropzone').attr('data-count', imagecount);
});
},
}
}
}// JavaScript Document
function openImagePopup(id = null) {
$(".upload-images").show();
$.ajax({
url: 'fetch.php',
type: 'post',
data: {id: id},
dataType: 'json',
success:function(response) {
var imagecount = response.counts;
$('.dropzone').attr('data-count', imagecount);
}
});
}
HTML
<form action="data.php" class="dropzone files-container" data-count="">
<div class="fallback">
<input name="file" type="file" multiple />
</div>
<input type="hidden" id="imageId" name="imageId">
</form>
UPDATED ANSWER
Once instanciated, the Dropzone plugin will remains with the same options unless you change the instance inner options directly.
To change options of a Dropzone, you can do this with the following line:
$('.dropzone')[0].dropzone.options.maxFiles = newValue;
$('.dropzone')[0] returns the first dropzone DOM element
.dropzone.options return the underlying plugin instance options of the Dropzone. You can now change any options directly on this object.
In you case, you will have to change the function that initiate the popup like follow
function openImagePopup(id = null) {
$(".upload-images").show();
$.ajax({
url: 'fetch.php',
type: 'post',
data: {id: id},
dataType: 'json',
success:function(response) {
var imagecount = response.counts;
$('.dropzone')[0].dropzone.options.maxFiles = imagecount;
}
});
}
And change the dropzone onSuccess event like this:
onyxDropzone.on("success", function(file, response) {
let parsedResponse = JSON.parse(response);
file.upload_ticket = parsedResponse.file_link;
var imagecount = $('.dropzone')[0].dropzone.options.maxFiles - 1;
$('.dropzone')[0].dropzone.options.maxFiles = imagecount;
});
As you can see, You can also remove the data-count="" attribute on you element and reuse the value from the plugin instance options.maxFiles
After spending a couple of hours of trials and errors I realized using the maxFiles setting from Dropzone is not exactly what is expected in many cases. That setting will only limit uploading files through the explorer / drag&drop, but after reload more files can be uploaded. It also does not reflect any failures to the upload on the serrver side (e.g. file size too big).
Changing the value of the maxFiles setting of an already initialized Dropzone from outside ot it is impossible. For example reseting the number of allowed files after removing some images with ajax will not work.
To really control the number of files that can be uploaded to the server the counting must take place on the server. Then in the Dropzone, in the success function, we should handle the ajax response:
success: function (file, response) {
var response_data = jQuery.parseJSON(response);
if(!response_data.success) {
$(file.previewElement).addClass('dz-error');
$(file.previewElement).addClass('dz- complete');
$(file.previewElement).find('.dz-error-message').text(response_data.error);
}
}
The response is the feedback information provided by the script assigned to the action attribute of the Dropzone <form>, e.g. <form action="/uploader">.

Preventing multiple requests from ajax

I have "load more" button, and if I click it fast enough it load the same content twice, and I want to prevent it.
This is how I call to the load more with ajax:
<script type="text/javascript">
function loadmore() {
var val = document.getElementById("result_no").value;
var userval = document.getElementById("user_id").value;
$.ajax({
type: 'post',
url: 'fetch.php',
data: {
getresult: val,
getuserid: userval
},
context: this,
success: function(response) {
var content = document.getElementById("result_para");
content.innerHTML = content.innerHTML + response;
document.getElementById("result_no").value = Number(val) + 10;
}
});
}
</script>
<div id="content">
<div id="result_para">
</div>
</div>
<input type="hidden" id="user_id" value="<?php echo $userid;?>">
<input type="hidden" id="result_no" value="15">
<input type="button" id="load" onclick="loadmore()" value="Load More Results">
You could set a loading variable to true at the start of loadmore, and set it back to false in the ajax callback. loading should be declared outside of loadmore though (see what a closure is).
var loading = false;
function loadmore()
{
if (loading) {
return ;
}
loading = true;
var val = document.getElementById("result_no").value;
var userval = document.getElementById("user_id").value;
$.ajax({
type: 'post',
url: 'fetch.php',
data: {
getresult:val,
getuserid:userval
},
context: this,
success: function (response) {
loading = false;
var content = document.getElementById("result_para");
content.innerHTML = content.innerHTML+response;
document.getElementById("result_no").value = Number(val)+10;
},
error: function () {
loading = false;
}
});
}
Instead of using that variable, you could also programmatically disable/enable the button, but that means that your button will flicker if the request is fast.
You can prevent from this by disable the button after first click, so change this lines:
success: function (response) {
var content = document.getElementById("result_para");
content.innerHTML = content.innerHTML+response;
document.getElementById("result_no").value = Number(val)+10;
}
With this lines:
success: function (response) {
document.getElementById("load").disabled = true;
var content = document.getElementById("result_para");
content.innerHTML = content.innerHTML+response;
document.getElementById("result_no").value = Number(val)+10;
document.getElementById("load").disabled = false;
}
you could disable the button when the "load more" button is clicked then then use the javascript function setTimeout to remove the disabled attribute from the button after a period of time. This would mean that the button would not be able to be clicked after the first click and even if the ajax request returned an error the button would still be able to be clicked.
$('#load').click(function {
// disable the button
$(this).prop('disabled', true);
// after three seconds enable the button again
var timeout = setTimeout(function() { $(this).prop('disabled', false); }, 3000);
});

Multiple POSTs with jQuery and AJAX

I'm having an issue with posting data via AJAX through a drag and drop interface. The data indeed is hitting my POST URL as defined, however, each and every time, the POST hits twice thereby causing the processing URL to handle the data again.
The premise of my application (at least this piece of it) was starting by basically using the code found at http://jsfiddle.net/UjQVw/2/ and to modify it for my needs.
I needed to have a container of items (in this case names) that were draggable to a user-defined number of divs on the opposite side of the screen -- whereby making 'room assignments' with a list of people.
Everything, except for the double POST is working well. If anyone can assist, I'd be most appreciative!
SAMPLE HTML CODE:
<div class="parent_list">
<h1>Registrants</h1>
<ul id="unplaced" class="group">
<?
foreach ($obj->function as $key => $value)
{
?>
<li data-group-id="0" data-post-id="<?=$value["rmid"]?>">
<?=$value["lname"]?>, <?=$value["fname"]?>
</li>
<?
}
?>
</ul>
</div>
<div class="lists">
<h1>Rooms</h1>
<ul style="display:none" id="new_list" class="group"></ul>
</div>
<input type="button" id='add' value="+ Add Room"/>
SAMPLE JS
<script>
var count = 0;
$("#add").click(function() {
count++;
var $clone = $("#new_list").clone();
$clone.attr({
id: count,
style: "" // remove "display:none"
});
$clone.find(".group").each(function(){
$(this).attr({
id: $(this).attr("id") + count
});
});
$(".lists").append($clone);
$('.group').sortable({
connectWith: '.group',
update: function(event, ui) {
var lodging = new Array();
$('.group li').each(function(i) {
var id = $(this).attr('data-post-id');
var group = $(this).parent().attr('id');
lodging.push(group+'_'+id);
});
console.log(event);
$.ajax({
type : "POST",
cache : false,
url : 'lodging_process.php',
data: {
'lodging[]': lodging
},
});
}
});
});
</script>
You could always buffer it with a boolean.
<script>
var sending = false; //Buffering variable
var count = 0;
$("#add").click(function() {
count++;
var $clone = $("#new_list").clone();
$clone.attr({
id: count,
style: "" // remove "display:none"
});
$clone.find(".group").each(function(){
$(this).attr({
id: $(this).attr("id") + count
});
});
$(".lists").append($clone);
$('.group').sortable({
connectWith: '.group',
update: function(event, ui) {
var lodging = new Array();
$('.group li').each(function(i) {
var id = $(this).attr('data-post-id');
var group = $(this).parent().attr('id');
lodging.push(group+'_'+id);
});
console.log(event);
if(!sending) { //Make sure we are not already sending a request
sending = true;
$.ajax({
type : "POST",
cache : false,
url : 'lodging_process.php',
data: {
'lodging[]': lodging
},
success: {
sending = false; //Upon finishing, allow another ajax command of this type
},
error: {
sending = false;
}
});
}
}
});
});
</script>
See if that works.
After the response by #John, I did some more testing and looking around and found this gem that's apparently stumped several others by me. As stated in the original question, the POST was indeed working...it was simply posting TWICE after each event. The reason for this is that there were changes in BOTH lists, thereby initiating the callback for EACH list that's affected.
Adding this simple if check as outlined here: https://forum.jquery.com/topic/sortables-update-callback-and-connectwith
update:function(e,ui) {
if (this === ui.item.parent()[0]) {
//your code here
}
}
has done the trick for me. Hope this information helps others with multiple callbacks using jQuery sortable and connectWith functions.
So...the new JS looks like this:
<script>
var count = 0;
$("#add").click(function() {
count++;
var $clone = $("#new_list").clone();
$clone.attr({
id: count,
style: "" // remove "display:none"
});
$clone.find(".group").each(function(){
$(this).attr({
id: $(this).attr("id") + count
});
});
$(".lists").append($clone);
$('.group').sortable({
connectWith: '.group',
update: function(event, ui) {
if (this == ui.item.parent()[0]) {
var lodging = new Array();
$('.group li').each(function(i) {
var id = $(this).attr('data-post-id');
var group = $(this).parent().attr('id');
lodging.push(group+'_'+id);
});
$.ajax({
type : "POST",
cache : false,
url : 'lodging_process.php',
data: {
'lodging[]': lodging
},
});
}
}
});
});
</script>

Show a loading image is not working well

I have defined the following script as part of implementing paging :-
var getPage = function () {
var $a = $(this);
var options = {
url: $a.attr("href"),
data: $("form").serialize(),
type: "get"
};
$.ajax(options).done(function (data) {
$(".loadingimage").show();
var target = $a.parents("div.pagedList").attr("data-tms-target");
$(target).replaceWith(data);
});
return false;
};
$(document).ready(function () {
$(".main-content").on("click", ".pagedList a", getPage);
})
And part of the mark-up is as follow:-
<div id="AuditTable">
<div class="pagedList" data-tms-target="#AuditTable">
#Html.PagedListPager(Model , page => Url.Action("Index",new { page }),
PagedListRenderOptions.ClassicPlusFirstAndLast)
</div> <img src="~/Content/Ajax-loader-bar.gif" class="loadingimage" id="progress2" />
<table class="table table-striped table-bordered bootstrap-datatable datatable">
<thead><tr>
The paging will work well , but the problem is that the
$(".loadingimage").show();
Will not show the hidden loading image during data retrieval, can anyone advice on this problem ?
Try these
You can load the image in your browser (e.g. http://yourdomain.com/Content/Ajax-loader-bar.gif) If you can, consider writing full url as image src.
Try id as selector (e.g. $("#progress2).show(); )
If those are not leading you to anywhere you can put the image into a div, remove its class (assume that you hide it with css), .show(); and .hide(); within getPage function.
HTML:
<div id="loadcontainer"><img src="Content/Ajax-loader-bar.gif" id="progress2" /></div>
Javascript:
var getPage = function () {
$("#loadcontainer").show();
var $a = $(this);
var options = {
url: $a.attr("href"),
data: $("form").serialize(),
type: "get"
};
$.ajax(options).done(function (data) {
$("#loadcontainer").hide();
var target = $a.parents("div.pagedList").attr("data-tms-target");
$(target).replaceWith(data);
});
return false;
};

Ajax call in a jQuery plugin not working properly

I'm trying to create a jQuery plugin, inside I need to do an AJAX call to load an xml.
jQuery.fn.imagetags = function(options) {
s = jQuery.extend({
height:null,
width:null,
url:false,
callback:null,
title:null,
}, options);
return this.each(function(){
obj = $(this);
//Initialising the placeholder
$holder = $('<div />')
.width(s.width).height(s.height)
.addClass('jimageholder')
.css({
position: 'relative',
});
obj.wrap($holder);
$.ajax({
type: "GET",
url: s.url,
dataType: "xml",
success:function(data){ initGrids(obj,data,s.callback,s.title); } ,
error: function(data) { alert("Error loading Grid data."); },
});
function initGrids(obj, data,callback,gridtitle){
if (!data) {
alert("Error loading Grid data");
}
$("gridlist gridset",data).each(function(){
var gridsetname = $(this).children("setname").text();
var gridsetcolor = "";
if ($(this).children("color").text() != "") {
gridsetcolor = $(this).children("color").text();
}
$(this).children("grid").each(function(){
var gridcolor = gridsetcolor;
//This colour will override colour set for the grid set
if ($(this).children("color").text() != "") {
gridcolor = $(this).children("color").text();
}
//addGrid(gridsetname,id,x,y,height,width)
addGrid(
obj,
gridsetname,
$(this).children("id").text(),
$(this).children("x").text(),
$(this).children("y").text(),
$(this).children("height").text(),
$(this).children("width").text(),
gridcolor,
gridtitle
);
});
});
}
function addGrid(obj,gridsetname,id,x,y,height,width,color,gridtitle){
//To compensate for the 2px border
height-=4;
width-=4;
$grid = $('<div />')
.addClass(gridsetname)
.attr("id",id)
.addClass('gridtag')
.imagetagsResetHighlight()
.css({
"bottom":y+"px",
"left":x+"px",
"height":height+"px",
"width":width+"px",
});
if(gridtitle != null){
$grid.attr("title",gridtitle);
}
if(color != ""){
$grid.css({
"border-color":color,
});
}
obj.after($grid);
}
});
}
The above plugin I bind with 2 DOM objects and loads two seperate XML files but the callback function is run only on the last DOM object using both loaded XML files.
How can I fix this, so that the callback is applied on the corresponding DOMs. Is the above ajax call is correct?
Sample usage:
<script type="text/javascript">
$(function(){
$(".romeo img").imagetags({
height:500,
width:497,
url: "sample-data.xml",
title: "Testing...",
callback:function(id){
console.log(id);
},
});
});
</script>
<div class="padding-10 min-item background-color-black">
<div class="romeo"><img src="images/samplecontent/test_500x497.gif" alt="Image"> </div>
</div>
<script type="text/javascript">
$(function(){
$(".romeo2 img").imagetags({
height:500,
width:497,
url: "sample-data2.xml",
title: "Testing...",
callback:function(id){
console.log(id);
},
});
});
</script>
<div class="padding-10 min-item background-color-black">
<div class="romeo2"><img src="images/samplecontent/test2_500x497.gif" alt="Image"> </div>
</div>
Here is the sample XML data:
<?xml version="1.0" encoding="utf-8"?>
<gridlist>
<gridset>
<setname>gridset4</setname>
<color>#00FF00</color>
<grid>
<color>#FF77FF</color>
<id>grid2-324</id>
<x>300</x>
<y>300</y>
<height>60</height>
<width>60</width>
</grid>
</gridset>
<gridset>
<setname>gridset3</setname>
<color>#00FF00</color>
<grid>
<color>#FF77FF</color>
<id>grid2-212</id>
<x>300</x>
<y>300</y>
<height>100</height>
<width>100</width>
</grid>
<grid>
<color>#FF77FF</color>
<id>grid2-1212</id>
<x>200</x>
<y>10</y>
<height>200</height>
<width>10</width>
</grid>
</gridset>
</gridlist>
You might be experiencing issues because your calling the ajax load on same url, thus the second call cancels the first call.
If you reading in the same url for each div, why don't you call the ajax once then loop the elements when it returns.
jQuery.fn.imagetags = function(options) {
s = jQuery.extend({
height:null,
width:null,
url:false,
callback:null,
title:null,
}, options);
var elems = $(this);
$.ajax({
type: "GET",
url: s.url,
dataType: "xml",
success:function(data){
elems.each(function() {
obj = $(this);
//Initialising the placeholder
$holder = $('<div />')
.width(s.width).height(s.height)
.addClass('jimageholder')
.css({
position: 'relative',
});
obj.wrap($holder);
initGrids(obj,data,s.callback,s.title);
});
},
error: function(data) { alert("Error loading Grid data."); }
});
return $(this);
}
Basically, what your doing here is calling the ajax function then instantly return the set. then, when the ajax callback gets fired, your looping the elements and appending the data.
This might be a scoping issue. You should use the 'var' statement when declaring variables inside functions. Otherwise, the variables go into the global scope.
var s = jQuery.extend({
height:null,
width:null,
url:false,
callback:null,
title:null,
}, options);
elems.each(function() {
var obj = $(this);
....
}
Since the variables are living in the global scope, they get overwritten by each iteration through the loop, and ultimately resulting in the the last DOM element.

Categories

Resources