using promise pattern in a loop - javascript

I need to loop thru div's and load them using the promise pattern but apparently only the data from the last call gets displayed.
Here is my code
$('div[class=ceTable]').each(function () {
var position = $(this).position();
gridID = $(this).attr('id')
tableID = $(this).attr("data-tableid")
docId = $(this).attr("data-docid")
headerFound = $(this).data("headerFound")
headerArray = $(this).data("headerArray")
columnCount = $(this).data("columnCount")
$.ajax({
type: "GET",
dataType: "json",
url: "ajaxGetTableData",
data: {
'docID': docId,
'tableID': tableID
},
beforeSend: function () {
$('#' + gridID).block({
css: {
border: 'none',
padding: '15px',
backgroundColor: '#36a9e1',
'-webkit-border-radius': '10px',
'-moz-border-radius': '10px',
opacity: 5,
color: '#fff'
},
message: 'Loading Grid'
});
}
}).done(function (data) {
console.log(data, "ajaxGetTableData")
ceFeature.generateGridFromJSONObject({
tabledata: data,
columnCount: columnCount,
gridID: gridID,
headerArray: headerArray,
headerFound: headerFound
})
$('#' + gridID).unblock();
})

Your variables are implicitly global (as you forgot the var keyword) so each iteration will overwrite the previous values. The async callbacks will only access the last one then - the typical creating functions in a loop problem.
To fix this, make the variables local to the function (the each callback) so that it makes the success callback a closure with the respective variables in its scope:
$('div[class=ceTable]').each(function () {
var position = $(this).position(),
gridID = $(this).attr('id'),
tableID = $(this).attr("data-tableid"),
docId = $(this).attr("data-docid"),
headerFound = $(this).data("headerFound"),
headerArray = $(this).data("headerArray"),
columnCount = $(this).data("columnCount");
…

Using a closure:
$('div[class=ceTable]').each(function () {
var position = $(this).position();
gridID = $(this).attr('id')
tableID = $(this).attr("data-tableid")
docId = $(this).attr("data-docid")
headerFound = $(this).data("headerFound")
headerArray = $(this).data("headerArray")
columnCount = $(this).data("columnCount")
(function (columnCount, gridID, headerArray, headerFound) {
$.ajax().done();
}(columnCount, gridID, headerArray, headerFound));
});

Related

FullCalendar events colors

I have a calendar, and outside of this I have a box where I put the event values (client, barber, service and I choose a color). After loading the values, an element is generated that I can select and drag to the calendar. The following happens to me:
When I create an event and drag it to the calendar, it is placed with the color that I configured. If I click the save button, it loads correctly into the database. A json is saved with the event information, for example:
{"id":2,"title":"Maria Marco","barbero":"Diego","servicio":"Corte","start":"2020-03-21T10:30:00","end":"2020-03-21T11:00:00","color":"rgb(0, 86, 179)"}
Suppose I don't have any items in the database, and I create 3 events and drag them to the calendar. If I click the save button, these 3 will be saved correctly as indicated above.
Now if I do a new event load, these new elements will load correctly, but in the previous elements the color property now disappears.
I appreciate if any find the error in this spaghetti of js
$(function() {
var containerEl = document.getElementById('external-events');
var calendarEl = document.getElementById('calendar');
// initialize the external events
// -----------------------------------------------------------------
new FullCalendarInteraction.Draggable(containerEl, {
itemSelector: '.external-event',
eventData: function(eventEl) {
var barbero = $("#barbero").children(".opcion-barbero:selected").html()
var servicio = $("#servicio").val()
return {
title: eventEl.innerText,
extendedProps: { "barbero": barbero, "servicio": servicio, "color": eventEl.style.backgroundColor },
backgroundColor: eventEl.style.backgroundColor,
borderColor: eventEl.style.backgroundColor
};
}
});
view = 'timeGridDay';
header = {
left: 'prev,next timeGridDay,timeGridWeek,dayGridMonth',
center: '',
right: ''
};
var calendar = new FullCalendar.Calendar(calendarEl, {
timeZone: 'local',
plugins: ['interaction', 'dayGrid', 'timeGrid'],
eventSources: [
// your event source
{
url: 'ajax/turnos2.ajax.php'
}
],
editable: true,
droppable: true, // this allows things to be dropped onto the calendar !!!
drop: function(info) {
info.draggedEl.parentNode.removeChild(info.draggedEl);
}
});
calendar.render();
/* ADDING EVENTS */
var currColor = '#3c8dbc' //Red by default
//Color chooser button
var colorChooser = $('#color-chooser-btn')
$('#color-chooser > li > a').click(function(e) {
e.preventDefault()
//Save color
currColor = $(this).css('color')
//Add color effect to button
$('#add-new-event').css({
'background-color': currColor,
'border-color': currColor
})
})
$('#add-new-event').click(function(e) {
e.preventDefault()
//Get value and make sure it is not null
var val = $('#new-event').val()
if (val.length == 0) {
return
}
//Create events
var event = $('<div />')
event.css({
'font-weight': 300,
'background-color': currColor,
'border-color': currColor,
'color': '#fff'
}).addClass('external-event')
event.html(val)
$('#external-events').prepend(event)
//Add draggable funtionality
ini_events(event)
//Remove event from text input
$('#new-event').val('')
})
/*==============================================
Apply changes to the events
==============================================*/
$(document).on("click", "span.guardarCalendario", function() {
var arrayEventos = new Array();
var eventos = calendar.getEvents();
// Contador para ID
var num = 1;
eventos.forEach(e => {
// Nombre del turno
title = (e._def["title"]);
barbero2 = (e._def.extendedProps["barbero"]);
servicio = (e._def.extendedProps["servicio"]);
color = (e._def.extendedProps["color"]);
id = num;
num = num + 1;
var evento = new Object();
evento["id"] = id;
evento["title"] = title;
evento["barbero"] = barbero2;
evento["servicio"] = servicio;
evento["start"] = start;
evento["end"] = end;
evento["color"] = (e._def.extendedProps["color"]);
arrayEventos.push(evento);
})
$("#turnos").val(JSON.stringify(arrayEventos))
var data = { 'data': JSON.stringify(arrayEventos) }
$.ajax({
type: 'POST',
url: 'ajax/turnos.ajax.php',
dataType: 'json',
data: data,
success: function(data, status, xhr) {
alert("response was " + data);
},
error: function(xhr, status, errorMessage) {
$("#debug").append("RESPONSE: " + xhr.responseText + ", error: " + errorMessage);
}
});
})
turnos.ajax.php
<?php
require_once "../modelos/turnos.modelo.php";
require_once "../controladores/turnos.controlador.php";
class AjaxTurnos{
public $data;
public function ajaxActualizarTurnos(){
$datos = ($this->data);
foreach(json_decode($datos) as $value){
$respuesta = ModeloTurnos::mdlActualizarTurnos(json_encode($value).PHP_EOL);
}
return $respuesta;
}
}
/*==============================
ACTUALIZAR TURNOS
==============================*/
if(isset($_POST["data"])){
ModeloTurnos::mdlTruncarTurnos();
$turnos = new AjaxTurnos();
$turnos -> data = $_POST["data"];
$turnos -> ajaxActualizarTurnos();
}
turnos2.ajax.php
<?php
require_once "../modelos/turnos.modelo.php";
require_once "../controladores/turnos.controlador.php";
$data = ControladorTurnos::ctrMostrarTurnos();
$data2 = [];
foreach($data as $key=>$value){
$data2[] = json_decode($value["datos"]);
}
//returns data as JSON format
echo (json_encode($data2));

Adding search button and text box in ui-dialog-buttonpane

I am writing a greasemonkey script to manipulates the DOM, queries a server and displays the result on a separate jquery dialog.
I want to add following two functionalities to it:
Provide a search box which acts like a simple search on a browser (i.e. searches through the content of the jquery dialog only and highlights the text).
Provide a text-box, the content of which should be stored permanently for all future use of the userscript unless the user changes it specifically.
The problem I am facing is that I want to include both of these in the ui-dialog-buttonpane area of the dialog, to the left of the close button, but I am not able to figure out how to do that.
What I do know is that I can use window.find() (as used here http://www.javascripter.net/faq/searchin.htm) to enable the browser find functionality.
Can someone help me with this ? Following is the code for my existing greasemonkey script:
// ==UserScript==
// #name Query for each URL Asynchronously
// #namespace SupportScript
// #include *
// #require https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js
// #require https://ajax.googleapis.com/ajax/libs/jquery/ui/1.11.0/jquery-ui.min.js
// #resource jqUI_CSS https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/themes/redmond/jquery-ui.css
// #grant GM_addStyle
// #grant GM_getResourceText
// #grant GM_getResourceURL
// #run-at document-end
// allow pasting
// ==/UserScript==
var snapshotResults = document.evaluate('//a[contains(#href,"http")]/#href', document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
var windowWidth = $(window).width()-800;
var windowHeight = $(window).height();
var zNode = document.createElement ('input');
zNode.setAttribute ('id', 'SSButton');
zNode.setAttribute( 'type', 'image' );
zNode.setAttribute( 'src', 'http://www.veryicon.com/icon/64/System/Longhorn%20R2/Back%20Button.png');
//zNode.setAttribute( 'src', 'https://dperkins.org/2013/2013-07-24.Icon.2.png');
//zNode.setAttribute( 'src','http://i1043.photobucket.com/albums/b433/suzuki800/Button-Info-icon.png');
document.body.appendChild (zNode);
var batchSize = 10;
var urlsToUpsert = [];
var uniqueHostnameSet = new Set();
var uniqueURLArray = [];
uniqueHostnameSet.add(window.location.hostname);
var finalUrl = window.location.protocol + '//' + window.location.hostname;
uniqueURLArray.push(finalUrl);
for (var iterate = 0; iterate < snapshotResults.snapshotLength; iterate++)
{
var hrefContent = snapshotResults.snapshotItem(iterate).textContent;
var regex = /http.*/;
var href = regex.exec(hrefContent);
var a = document.createElement('a');
a.href = href;
if (!uniqueHostnameSet.has(a.hostname))
{
uniqueHostnameSet.add(a.hostname);
finalUrl = a.protocol + '//' + a.hostname;
uniqueURLArray.push(finalUrl);
}
}
var divMain = '<div id="SSOverlayDialog"></div>';
$('body').append(divMain);
$.Coral = function (options) {
$.extend(options, {
url: "my URL",
data: JSON.stringify(options.data),
dataType: 'json',
crossDomain: true,
type: 'POST',
contentType: 'application/json',
processData: false,
headers: {
'Content-Encoding': 'abc',
'X-Target': options.operation
},
dataFilter: function(data, type) {
return data || "{}";
}
});
return $.ajax(options);
};
$.GetOperation = function (options) {
$.extend(options, {
async: true,
success: function(data) {
handleData(data);
},
operation: 'opeartion1'
});
return $.Coral(options);
};
$.UpsertOperation = function (options) {
$.extend(options, {
async: true,
operation: 'Operation2'
});
return $.Coral(options);
};
for (var iterateUniqueURLArray=0; iterateUniqueURLArray<uniqueURLArray.length; iterateUniqueURLArray+=batchSize) {
var urlList = uniqueURLArray.slice(iterateUniqueURLArray,iterateUniqueURLArray+batchSize);
try {
var listOfURLs = {
storeUrlList: urlList
};
var dataGetAttributes = {data: listOfURLs};
$.GetOperation(dataGetAttributes);
} catch(e) {
console.log(e);
}
}
function handleData (data) {
var div = '<div id="SSOverlayDialog">';
var response = JSON.stringify(data);
var subString = "";
var startIndex = response.indexOf('{',1);
var endIndex = response.lastIndexOf('}');
var responseText = response.substring(startIndex,endIndex);
var subString = JSON.parse(responseText);
$.each( subString, function( key, value ) {
key = JSON.stringify(key);
div+='<b><i><a style="color:#0645AD" href="'+key.substring(1,key.length-1)+'"><u>' + key.substring(1,key.length-1) + '</u></a></i></b><br><br>';
if(JSON.stringify(value)==='{}') {
console.log("Value for URL "+key+" is null.");
div+='<p>This URL does not exist with Mobius.<span style="color:red" class="urlNotPresent" id ="'+key.substring(1,key.length-1)+'"><u>Click Here</u></span> to submit to Mobius.</p>';
}
$.each( value, function( ky, val ) {
ky = JSON.stringify(ky);
if (val==null) {
div += '<p><b>'+ky.substring(1,ky.length-1)+': </b><i>'+val+'</i></p>';
}
else{
val = JSON.stringify(val);
div += '<p><b>'+ky.substring(1,ky.length-1)+': </b><i>'+val.substring(1,val.length-1)+'</i></p>';
};
});
div+='<br>';
});
div += '</div>';
$('#SSOverlayDialog').append(div);
$(".urlNotPresent").off('click');
$(".urlNotPresent").one('click', urlNotPresentFn);
$(".urlNotPresent").hover(pointerToClick, pointerToDefault);
}
var urlNotPresentFn = function() {
var url = jQuery(this).attr("id");
if (urlsToUpsert.length == batchSize-1) {
urlsToUpsert.push(url);
var listOfURLs = {
storeUrlList: urlsToUpsert
};
var myOptions = {data: listOfURLs};
$.UpsertOperation(myOptions);
urlsToUpsert.length = 0;
} else {
urlsToUpsert.push(url);
};
console.log(urlsToUpsert);
}
var pointerToClick = function() {
$(".urlNotPresent").css("cursor", "pointer");
}
var pointerToDefault = function(){
$(".urlNotPresent").css("cursor", "default");
}
$(window).bind('beforeunload', function() {
if(urlsToUpsert.length>0) {
var listOfURLs = {
storeUrlList: urlsToUpsert
};
var myOptions = {data: listOfURLs};
$.UpsertOperation(myOptions);
urlsToUpsert.length = 0;
};
return ;
});
$('#SSOverlayDialog').dialog({
autoOpen: false,
modal: false,
title: 'Discovered URLs (press "Esc" button to close)',
position: {
at: 'right top'
},
resizable: false,
width: windowWidth,
height: windowHeight,
open: function(event, ui) { $(".ui-dialog-titlebar-close").hide(); },
zIndex: 11111111,
buttons: [
{
text: 'Close',
click: function () {
$(this).dialog('close');
}
}
]
});
$("#SSButton").click(function() {
($("#SSOverlayDialog").dialog("isOpen") == false) ? $("#SSOverlayDialog").dialog("open") : $("#SSOverlayDialog").dialog("close") ;
/* if ($("#SSOverlayDialog").dialog("isOpen") == false) {
$("#SSOverlayDialog").dialog("open"),
$('#SSButton').css({
'transform': 'rotate(180deg)',
'transform': 'translate(-windowWidth)'
});
} else{
$("#SSOverlayDialog").dialog("close"),
$('#SSButton').css({
'transform': 'initial'
});
};*/
});
var jqUI_CssSrc = GM_getResourceText('jqUI_CSS');
jqUI_CssSrc = jqUI_CssSrc.replace(/\.ui-front \{[\s]*z-index:\s100\;[\s]*\}/g,".ui-front \{\n z-index: 20000000 \; \n\}");
GM_addStyle(jqUI_CssSrc);
GM_addStyle ( multilineStr ( function () {/*!
#SSButton {
background: none repeat scroll 0% 0% ;
background-image: none;
background-repeat: repeat;
background-attachment: scroll;
background-position: 0% 0%;
background-size: auto auto;
overflow: hidden;
position: absolute;
top: 0;
right: 0;
z-index: 22222222;
width: 40px;
height: 40px;
}
*/} ) );
function multilineStr (multiLineStringFn) {
var str = multiLineStringFn.toString ();
str = str.replace (/^[^\/]+\/\*!?/, '') // Strip function () { /*!
.replace (/\s*\*\/\s*\}\s*$/, '') // Strip */ }
.replace (/\/\/.+$/gm, '') // Double-slash comments wreck CSS. Strip them.
;
return str;
}
To include controls to the left of the "Close" button in a ui-dialog-buttonpane, you can use the .prepend() function on the .ui-dialog-buttonset class like this:
$('.ui-dialog .ui-dialog-buttonset').prepend('<input type="text"/><button class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"><span class="ui-button-text">Search</span></button>');
You'll most likely want to add a selector for the specific dialog you're using to avoid adding this control to any dialog on the page. Based on your example, it would be something like this:
$('div[aria-describedby=SSOverlayDialog]').find('.ui-dialog-buttonset').prepend('<input type="text"/><button class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"><span class="ui-button-text">Search</span></button>');
Hope that helps answer the main problem.
Best of luck!

Bootstrap Popover Displaying the Same Contents

Has anyone worked with the bootstrap popover? I am facing a little difficulty implementing it.
I am creating movie thumbnails dynamically, and on mouseenter event, I am using the popover to display the details of the image. The problem is, the same details are displayed for all the images.
Here is some part of my code:
<script>
$(function () {
$(".get-movies").click(getEventHandler);
});
function getEventHandler() {
var name = $(".get-movie-name").val();
$.ajax({
url: "http://api.rottentomatoes.com/api/public/v1.0/movies.json?apikey=my_key&q=" + name + "&page_limit=5",
dataType: "jsonp",
success: function (response) {
$(".display-movie").empty();
var ul = $(".display-movie");
for (var i = 0; i < response.movies.length; i++) {
var img = $("<img>").attr("src", response.movies[i].posters.original)
.attr("id", i)
.attr("data-placement", "right")
.attr("class", "img-popover")
.on("mouseover", response, getPopOver)
.on("mouseout", hidePopOver)
.css({
width: 200,
height: 200,
margin: 20
});
var div = $("<div>")
.append(img)
$("<li>")
.append(div)
.appendTo(ul);
}
}
});
}
function getPopOver(info) {
console.log(info);
var image = '<img src = " ' +info.data.movies[info.target.id].posters.thumbnail+ ' " />';
$(".img-popover").popover({
title: info.data.movies[info.target.id].title,
content: image,
trigger: "hover",
html: true
})
}
function hidePopOver() {
console.log("Leaving here");
$(".img-popover").popover("hide");
}
</script>
I think your:
var name = $(".get-movie-name").val();
will return the first item in the collection of items that match that class.
you might try:
var name = $('#' +this.id + ".get-movie-name").val();
but without seeing some of the html, I cannot be exact here.

Displaying live highcharts data dynamically without alert

Below is my code ,Firstly i had fetched data from database using JSON,after that i binded initial 15 rows to chart,and in setInterval function i am continually binding 1 row after interval of 1 second ,My question is without alert i.e alert("hi") i am not getting initial result,how can i get result without alert?
$(function () {
$(document).ready(function () {
var Data = "";
var dataarray = [];
var IdArray = [];
var counter = 0;
var chart;
$('#container').highcharts({
chart: {
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function () {
var series = this.series[0];
setInterval(function () {
var i = 16 + counter;
var x = IdArray[i], // current time
y = dataarray[i];
series.addPoint([x, y], true, true);
counter = counter + 1;
}, 1000);
}
}
},
title: {`enter code here`
text: 'Live HighChart From Database'
},
xAxis: {
type: 'decimal'
},
yAxis: {
title: {
text: 'Value'
}
},
series: [{
name: 'Data from database',
data: (function () {
// generate an array of random data
$.ajax({
type: 'POST',
dataType: 'json',
contentType: 'application/json',
url: 'LiveHighchart.aspx/GetData',
data: '{}',
success:
function (response) {
Data = response.d;
for (var i = 0; i < Data.length; i++) {
dataarray[i] = Data[i].random;
IdArray[i] = Data[i].Id;
}
}
});
var data = [];
alert("hi");
for (var i = 0; i < 15; i++) {
data.push({
x: IdArray[i],
y: dataarray[i]
});
}
return data;
})()
}]
});
});
});
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<div id="container" style="min-width: 310px; height: 400px; margin: 0 auto">
</div>
</div>
</form>
</body>
</html>
I think it's because the query hasn't return the result yet - the alert is causing a pause in your app that means the result can be delivered in time. You should think about using callbacks - functions that only run when the data from your AJAX call is returned.
I Solved it myself ,code after ajax request was executing before ajax request loads data:
this line (async: false) in ajax request forced code after ajax to pause until ajax loads data

Hide a column in flexigrid

Is there a way to hide and show a column in jQuery flexigrid like this?
$('#FlexigridID').hideCol('ColumnName');
$('#FlexigridID').showCol('ColumnName');
New code tested:
$(function () {
var visible = true;
$('#yo').click(function () {
alert('hello');
visible = !visible;
showColumn('#yourFlexigridNameHere', 'Lastname', visible);
});
});
// you can put this in a separate javascript library
function showColumn(tbl, columnName, visible) {
var grd = $(tbl).closest('.flexigrid');
var colHeader = $('th[abbr=' + columnName + ']', grd);
var colIndex = $(colHeader).attr('axis').replace(/col/, "");
// queryVisible = $(colHeader).is(':visible');
// alert(queryVisible);
$(colHeader).toggle(visible);
$('tbody tr', grd).each(
function () {
$('td:eq(' + colIndex + ')', this).toggle(visible);
}
);
}
HTML:
<input id='yo' type="button" />
You can also set the hide to false on flexigrid's colModel setup:
colModel: [
{display: 'Row ID', name : 'Lastname', width : 100,
sortable : true, align: 'left', hide: false}
You can also add a method against flexigrid, you can put this in a separate javascript library:
(function ($) {
$.fn.showColumn = function (columnName, visible) {
if (visible == undefined) visible = true;
var grd = this.closest('.flexigrid');
var colHeader = $('th[abbr=' + columnName + ']', grd);
var colIndex = $(colHeader).attr('axis').replace(/col/, "");
$(colHeader).toggle(visible);
$('tbody tr', grd).each(
function () {
$('td:eq(' + colIndex + ')', this).toggle(visible);
}
);
};
$.fn.hideColumn = function (columnName) {
this.showColumn(columnName, false);
}
})(jQuery);
You can now invoke hiding and showing using these:
$('#FlexigridID').hideColumn('ColumnName');
$('#FlexigridID').showColumn('ColumnName');
visible = !visible; // for toggling need
$('#FlexigridID').showColumn('ColumnName', visible);
Try this:
$('#FlexigridID').find("tr td").eq(columnIndex).hide();
$('#FlexigridID').find("tr td").eq(columnIndex).show();
Try something like this
$('td:nth-child(2)').hide();
for table with header(th)
$('td:nth-child(2),th:nth-child(2)').hide();
Read more about Hide a Table Column with a Single line of jQuery code
$("#yourFlexigridNameHere").flexToggleCol(columnIndex, false);
//columnIndex - starts from 0

Categories

Resources