how to make incrementally added nodes persistent in manual navigation - javascript

Using the NetChart of zoomcharts (1.5.1), it seems that addData() only works for navigation = showall. In case I try using navigation = manual, it requires initialNodes.
Is there a way initialNodes automatically gets populated with existing data (that was added incrementally)? The reason I want that is because, I want to intially load a specific set of nodes/links using navigation = showall and then change it to navigation = manual so that user can click to see all neighbors
Basically, the following example shows this case... node 'f-1' is getting overwritten by initialNodes of 'm-1'.
<script>
var t = new NetChart({
container: document.getElementById("demo"),
area: { height: 350 }
});
t.addData({nodes: [{loaded: true,id: "f-1",name: "Anna"},{id: "m-1",name: "Joe"}],links: [{to: "f-1",from: "m-1",id: "l01",type: "friend"}]});
t.updateSettings({
data:
{
preloadNodeLinks:true,
dataFunction: function(nodeList, success, error){
//return just the first node, net chart will ask for more
jQuery.ajax({
url:"/dvsl/data/net-chart/friend-net/"+nodeList[0]+".json",
success: success,
error: error});
}
},
navigation:{
initialNodes:["m-1"],
mode:"manual"
}
});
</script>

Found a workaround by use of doubleclick:
<script>
var t = new NetChart({
container: document.getElementById("demo"),
area: {
height: 350
},
events:{
onDoubleClick: dclickEvent
}
});
t.addData({nodes: [{loaded: true,id: "f-1",name: "Anna"},{id: "m-1",name: "Joe"}],links: [{to: "f-1",from: "m-1",id: "l01",type: "friend"}]});
function dclickEvent(event){
if (!$("#click")[0].checked) return;
console.log('event.clickNode', event.clickNode);
if (event.clickNode) {
jQuery.ajax({
url: "/dvsl/data/net-chart/friend-net/" + event.clickNode.id + ".json",
success: function(data) {
console.log('test-foo-data', data);
t.addData(data);
}
})
}
}
</script>

Related

Slickgrid changes the ID from my data and dont clean up the empty row

Im trying to update my grid without the need for refreshing! Right now, it updates only the grid, but dont know why, it changes the id to the last one inserted and dont "clean up" the empty row! When I try to insert data, it clears it .
Im kinda new with ajax and slickgrid! I've tried to see the ajax example from slickgrid, but I got some errors!
Do I need to re-upload the onCellChange and so on ? I just wanted to update th grid with the new data.
Any help?
Thanks in advance
So, I've tried re-draw the table re-using my actual drawning code, but im failling to re-draw with correct data.
Function to re-draw grid
function desenhaGrid() {
$("#myGrid").ready(function () {
$(function () {
$.ajax({
type: "GET",
url: '/SlickGrid/GetData',
dataType: 'json',
success: function (jsonResult) {
for (var key in jsonResult) {
if (jsonResult.hasOwnProperty(key)) {
//print table
var d = (data[key] = {});
for (var i = 0; i < data.length; i++) {
d["#"] = i + 1;
}
d["id"] = jsonResult[key].id;
d["t_nome"] = jsonResult[key].t_nome;
d["t_prof"] = jsonResult[key].t_prof;
d["t_data"] = jsonResult[key].t_data;
d["t_morada"] = jsonResult[key].t_morada;
d["t_percCompleto"] = jsonResult[key].t_percCompleto;
}
}
grid = new Slick.Grid("#myGrid", dataView, columns, options);
dataView.beginUpdate();
grid.invalidateAllRows();
dataView.setItems(data);
grid.render();
dataView.endUpdate();
}
});
});
});
}
and this is my onAddNewRow
grid.onAddNewRow.subscribe(function (e, args) {
var idData = jsonResult[key].id + 1;
var item = { "id": idData, "t_nome": '', "t_prof": '', "t_data": '', "t_morada": '', "t_percCompleto": '' };
$.extend(item, args.item);
dataView.addItem(item);
//if user press enter
grid.onKeyDown.subscribe(function (e) {
var keyPressed = event.keyCode || event.which;
if (keyPressed == 13) {
alert("add");
var myJSON = JSON.stringify(item);
$.post("/SlickGrid/addGridEnter", $("input[name=mydata]").val(myJSON));
console.log(myJSON);
desenhaGrid();
}
});
});
I expected it to re-draw my grid with all the data. Instead, its changing all the id's to the last one inserted and when I try to insert data in the last row, wont let me (it clears it after I leave the cell).
UPDATE:
I've udpate the function to draw the grid
function desenhaGrid() {
$("#myGrid").load(function () {
$(function () {
$.ajax({
type: "GET",
url: '/SlickGrid/GetData',
dataType: 'json',
success: function (jsonResult) {
dataView.beginUpdate();
grid.invalidateAllRows();
dataView.setItems(jsonResult);
dataView.endUpdate();
grid.render();
}
});
});
});
}
I don't think this is a SlickGrid issue. There are all kind of problems with the javascript. For example:
why are you using $("#myGrid").ready( ? the ready event only fires when the DOM has finished loading
the entire copy operation from jsonResult to data just ends up with the same data. why not use jsonResult directly?
the section for (var i = 0; i < data.length; i++) { d["#"] = i + 1; }
runs once for each row added to data, it should just run once at the end, outside of the loop
you are subscribing to the keydown event once for each row added to the grid. you should just subscribe once. listening for an Enter key is also a very poor method of determining if a row has been entered. what if someone clicks on another row before pressing Enter?
Slickgrid is a client-side grid. This means data does not need to be persisted after every change. It's a common approach to use a 'save' button, or detect if the active row has changed.

Communication between browser tabs: page titles must be updated synchronously for all browser tabs

what i have: page title is updating dynamically when new data is retrieving from ajax call; if tab with this page is visited - title is set to default value; if i open the second tab with this page, title of this tab is set to default (i must fix this)
what i need: page title must be the same for all tabs with this page. i mean, page title must be updated synchronously for all tabs.
My current implementation:
var prevData;
var newRequestsCounter = 0
var getRequests = function(){
$.ajax({
async: true,
type: "GET",
url: "/get_requests/",
success: function(data){
// retrieve and parse data. i skip this part
// newRequestsCounter is updating here
var visible = vis();
if (visible){
newRequestsCounter = 0
document.title = 'Default title'
} else {
if (newRequestsCounter == 0) {
document.title = 'Default title'
} else {
document.title = 'Dynamic title'
}
}
setTimeout(getRequests, 2000)
}
});
};
I tried with intercom.js, but it doesn't work properly. For some reason intercom.on gets different data each time. For example: first call - default title, second call - dynamic title. I checked with debug, wrong data comes after executing this line setTimeout(getRequests, 2000).
var intercom = Intercom.getInstance();
intercom.on('notice', function(data) {
document.title = data.title;
});
var prevData;
var newRequestsCounter = 0
var getRequests = function(){
$.ajax({
async: true,
type: "GET",
url: "/get_requests/",
success: function(data){
// retrieve and parse data. i skip this part
// newRequestsCounter is updating here
var visible = vis();
if (visible){
newRequestsCounter = 0
intercom.emit('notice', {title: 'Default title'});
} else {
if (newRequestsCounter == 0) {
intercom.emit('notice', {title: 'Default title'});
} else {
intercom.emit('notice', {title: 'Dynamic title'});
}
}
setTimeout(getRequests, 2000)
}
});
};
In general, i don't quite understand if it possible to achieve required functionality in scope of single ajax callback. I tried the next code. In this case variable "counter" from localStorage is incremented every time i open new tab. It means if i expect "3" in title for two tabs, i get "6" with two tabs instead.
var intercom = Intercom.getInstance();
intercom.on('notice', function(data) {
document.title = data.title;
});
if (localStorage.getItem("counter") === null){
localStorage.setItem("counter", 0);
}
var getRequests = function(){
$.ajax({
async: true,
type: "GET",
url: "/get_requests/",
success: function(data){
// skip part with retrieving and parsing data
var counter = localStorage.getItem("counter")
localStorage.setItem("counter", ++counter);
var visible = vis();
if (visible){
localStorage.setItem("counter", 0);
intercom.emit('notice', {title: 'Default'});
} else {
if (localStorage.getItem("counter") == 0 || localStorage.getItem("counter") === null) {
intercom.emit('notice', {title: 'Default'});
} else {
intercom.emit('notice', {title: '(' + localStorage.getItem("counter") + ') requests'});
}
}
setTimeout(getRequests, 2000)
}
});
};
getRequests();
The part I am not understanding in your code is where you are opening a new browser tab. But, if that happening somewhere and you want to set the title of that new tab as its opening you can do this:
var newTab = window.open('/page')
newTab.title = 'New Title';
are you using some kind of long polling?
Maybe you can synchronise those polling calls with the browser's time.
e.g. poll everytime the browser's time's seconds are even numbers. then each tab should send its request at the same time and get (almost) at the same time an answer to update there title

Animation effect before ajax call

I've watched several tutorials on how to load content without having to refresh the browser. I'm also using history pushState and popstate to update the url dynamically depending on what site that is displaying. However even if this code works, I would like to be able to make som page transition animation effects > call the Ajax function > then make some fadeIn animation effects. So far i've had no luck in trying to do so. I tried to read up on Ajax (beforeSend: function(){}), but the success function seems to execute before the (beforeSend) function. Is there anyone that could point me in the right direction, or tell me what i possibly am doing wrong? I'd appriciate it!
$(document).ready(function() {
var content, fetchAndInsert;
content = $('div#content');
// Fetches and inserts content into the container
fetchAndInsert = function(href) {
$.ajax({
url: 'http://localhost:8000/phpexample/content/' + href.split('/').pop(),
method: 'GET',
cache: false,
success: function(data) {
content.html(data);
}
});
};
// User goes back/forward
$(window).on('popstate', function() {
fetchAndInsert(location.pathname);
});
$('.buttonlink').click(function(){
var href = $(this).attr('href');
// Manipulate history
history.pushState(null, null, href);
// Fetch and insert content
fetchAndInsert(href);
return false;
});
});
Questions? Just ask!
Thanks beforehand!
/// E !
You need to use callbacks. The provided solutions will work, but not necessarily sequentially. $.animate() and $.ajax both run asynchronously. If unfamiliar with this term, here's a good intro: http://code.tutsplus.com/tutorials/event-based-programming-what-async-has-over-sync--net-30027
Here's what I might do:
fetchAndInsert = function(href) {
$('#some-element').animate({'opacity':'0.0'}, 1000, function () {
$.ajax({
url: 'http://localhost:8000/phpexample/content/' + href.split('/').pop(),
method: 'GET',
cache: false,
success: function(data) {
content.html(data);
content.animate({'opacity':'1.0'}, 1000);
}
});
});
};
That will fade out whatever is currently in content, fetch the new data, replace what's currently in content, and then fade back in.
I tried to read up on Ajax (beforeSend: function(){}), but the success
function seems to execute before the (beforeSend) function
You can wait for animation to complete before appending new content to html using .queue(), .promise(), .finish()
beforeSend: function() {
element.queue(function() {
$(this).animate({/* do animation stuff */:500}, {duration:5000}).dequeue()
});
},
success: function(content) {
element.finish().promise("fx").then(function() {
container.append(content).fadeIn()
})
}
var element = $("#loading").hide();
var container = $("#content");
var button = $("button");
var ajax = {
// do asynchronous stuff
request: function() {
return new $.Deferred(function(d) {
setTimeout(function() {
d.resolve("complete")
}, Math.random() * 5000)
})
},
beforeSend: function() {
element.fadeIn().queue(function() {
$(this).animate({
fontSize: 100
}, {
duration: 2500
}).dequeue()
});
},
success: function(content) {
element.finish().promise("fx").then(function() {
element.fadeOut("slow", function() {
$(this).css("fontSize", "inherit");
container.append(content + "<br>").fadeIn("slow");
button.removeAttr("disabled")
})
})
}
}
button.click(function() {
$(this).attr("disabled", "disabled");
$.when(ajax.beforeSend()).then(ajax.request).then(ajax.success)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div id="loading">loading...</div>
<div id="content"></div>
<button>load content</button>
jsfiddle https://jsfiddle.net/ajmL5g1a/
Try this:
fetchAndInsert = function(href) {
// Before send ajax. Do some effects here
$.ajax({
url: 'http://localhost:8000/phpexample/content/' + href.split('/').pop(),
method: 'GET',
cache: false,
success: function(data) {
// After loading. Do some effects here
content.html(data);
}
});
};
My solution:
fetchAndInsert = function(href) {
var timeBeforeAnimation = Date.now(), animationDuration = 500;
/* Do some animation, I assume that with jQuery,
so you probably know how much time is takes - store that
time in variable `animationDuration`. */
/* Run your "before" animation here. */
$.ajax({ ...,
success: function(data) {
/* Check, if request processing was longer than
animation time... */
var timeoutDuration = animationDuration -
(Date.now() - timeBeforeAnimation);
/* ...and if so, delay refreshing the content,
and perform the final animation. */
setTimeout(function() {
content.html(data);
/* Perfom final animation. */
}, Math.max(0, timeoutDuration);
}
});
};
I would probably try using some css for this.
#content {
opacity: 0;
transition: all 1s;
}
#content.fade-in {
opacity: 1;
}
...
const content = $('#content');
const btn = $('.buttonlink');
const success = data =>
content.html(data).addClass('fade-in');
const fetchAndInsert = url =>
$.ajax({ url, cache: 'false' }).done(success);
const getData = function(e) {
e.preventDefault();
content.removeClass('fade-in');
fetchAndInsert($(this).attr('href'));
};
btn.on('click', getData)

My javascript function only fires once

I have a pretty basic step by step wizard I created. When you select an option from a drop down menu on page 1, I load a new page via jQuery ajax. If you hit back, it loads the original page again.
However after loading the original page again, my modelSelect() function that loads page 2 stops working. Doesn't fire at all. I'm not exactly sure what I'm doing wrong.
I'm hoping someone can see what I'm doing wrong. My code is below:
//Collapse panel handling
var group = jQuery('.estimator-container');
jQuery('.tab-click').click(function() {
group.find('.collapse.in').collapse('hide');
jQuery(this).parent().toggleClass('active');
});
/* -------------------------------------- *\
New form handler
\* -------------------------------------- */
function modelSelect(v) {
jQuery('#page_2, .estimator-container').toggle();
// Ajax for loading page_2
jQuery.ajax({
type: "POST",
data: v,
success: function() {
jQuery('.estimator-app').load(templateUrl + "/page-estimator2.php?p=" + v);
}
});
}
jQuery('.estimator-panel').on('change', '.select-model', function() {
var v = jQuery(this).val();
modelSelect(v);
}); //end on change function
// Back and continue handling
jQuery('.estimator-app').on('click', '.estimator_form_btn_next', function() {
var backBtn = jQuery('.estimator_form_btn_back');
var continueBtn = jQuery('.estimator_form_btn_next');
var firstPage = jQuery('#contact-first-page');
var lastPage = jQuery('#contact-last-page');
if (firstPage.is(":visible")) {
firstPage.toggle();
lastPage.toggle();
}
}); //end continue
// Go back
jQuery('.estimator-app').on('click', '.estimator_form_btn_back', function() {
var backBtn = jQuery('.estimator_form_btn_back');
var continueBtn = jQuery('.estimator_form_btn_next');
var firstPage = jQuery('#contact-first-page');
var lastPage = jQuery('#contact-last-page');
if (lastPage.is(":visible")) {
firstPage.toggle();
lastPage.toggle();
} else {
jQuery.ajax({
type: "POST",
// data: v,
success: function() {
jQuery('.estimator-app').load(templateUrl + "/estimator-initial.php");
}
});
}
}); //end continue
Simple delegation.
Adding jQuery(document).on('change', '.select-model', function(){ on line 29 made it work.
Change your this line:
jQuery('.estimator-panel').on('change', '.select-model', function() {
to this
jQuery(document).off('change', '.select-model').on('change', '.select-model', function(e){
e.preventDefault();
because if HTML is loaded after page load OR by some kind of JS, you need to deattach event and then attach back,

Adding Gritter Message After Second Deletion

I'm trying to find out why when a user is deleted by clicking on the ajax-delete class icon and performs the deletion process it shows the gritter message after deletion however if you were to immediately delete another user afterwards it removes the previous gritter message but doesn't show another for that second deletion. Any ideas on why this could be?
EDIT: I have figured out that the issue belongs to the $.gritter.removeAll(); code line. When there is another existing notification it removes it but doesn't add the next notification.
Any ideas what I should do here?
var rowToDelete = null;
var basicTable = null;
var api_url = null;
$(document).ready(function() {});
$(document).on('click', '.ajax-delete', function(e)
{
console.log(basicTable);
e.preventDefault();
//defining it like this captures and optimizing the need to cycle over the DOM more than once
//in subsequent calls to the element specifically
$elem = $(this);
$parentElem = $elem.closest('tr');
rowToDelete = $parentElem.get(0);
api_url = $elem.attr('href');
runConfirmation($('td:eq(1)', $parentElem).text());
});
function runConfirmation(nameSting)
{
$mymodal = $('#myModal');
$('.modal-body p', $mymodal).html('Are you sure you want to delete this <strong>'+nameSting+'</strong>?');
$mymodal.modal('show');
}
$('#myModalConfirm').on('click', function(e) {
$.ajax({
type: 'post',
url: api_url,
data: { _method: 'DELETE' },
dataType: 'json',
success: function(response) {
$.gritter.removeAll();
var className = 'growl-danger';
if (response.status == "SUCCESS") {
className = 'growl-success';
basicTable.fnDeleteRow(basicTable.fnGetPosition(rowToDelete));
rowToDelete = null;
api_url = null;
}
$.gritter.add({
position: 'top-right',
fade_in_speed: 'medium',
fade_out_speed: 2000,
time: 6000,
title: response.title,
text: response.message,
class_name: className,
sticky: false
});
}
});
$('#myModal').modal('hide');
});
Replace the following line:
$.gritter.removeAll();
With
$('.gritter-item-wrapper').remove();

Categories