Reference Global jquery function variable within foreach loop - javascript

I want to change the value of a global jquery variable within the foreach loop every time there is a new model item. I want to add new dates to the calendar but cant do that until I can access these functions from foreach loop.
*edit***
I over simplified my example for the question which was answered correctly by vov v. The actual code will do a lot more than add a value as it will add data to a calendar. I've added more code to show what it will do a little better
jquery:
<div id="calendar" style="width: 500px;" />
<script type="text/javascript">
$(document).ready(function () {
var calendar = $('#calendar').glDatePicker(
{
showAlways: true,
borderSize: 0,
dowOffset: 1,
selectableDOW: [1, 2, 3, 4, 5],
selectableYears: [2012, 2013, 2014, 2015],
specialDates: [
{
date: new Date(2013, 0, 8),
data: { message: 'Meeting every day 8 of the month' },
repeatMonth: true
},
{
date: new Date(2013, 5, 7),
data: { message: 'Meeting every day 8 of the month' }
},
],
onClick: function (target, cell, date, data) {
target.val(date.getFullYear() + ' - ' +
date.getMonth() + ' - ' +
date.getDate());
if (data != null) {
alert(data.message + '\n' + date);
}
}
}).glDatePicker(true);
$('#visible').change(function () {
var showAlways = eval($(this).val());
calendar.options.showAlways = showAlways;
if (!showAlways) {
calendar.hide();
}
else {
calendar.show();
}
});
});
var value = 0;
$('#total').click(function () {
alert(value);
});
function add() {
// will eventually add new specialDates to the calendar taken from model items
//test lines
//value = value + 1;
//return value;
}
</script>
razor view:
<input type="button" id="total" />
#foreach (var item in Model){
if (item.AppointmentStatus == "active")
{
// item display code
#: <script type="text/javascript"> add();</script>
}
if (item.AppointmentStatus == "history")
{
// item display code
}
}
I run this and get error below as it doesnt see the other code
'0x800a1391 - JavaScript runtime error: 'add' is undefined'

If you just want to capture "a count" that you want to send down to your client then you can simply do it like this:
<script>
var value = '#Model.Count';
// the rest of you script goes here
$(document).ready(function () {
$('#total').click(function () {
alert(value);
}
});
</script>
So say you have 7 items in your model, then the html that will be generated is this:
var value = 7;
and when you click on that total element it will give you an alert with the text 7.

Try moving your add function and variable declaration outside of doc ready. The functions in doc ready are not available until your razor has executed.

Related

Using AJAX, JavaScript to call python flask function with return to JavaScript

I know that you can have javascript to call a python flask function and be able to return data to a designated id. Like this:
HTML
<div id = "update"> </div>
<script type="text/javascript">
var counter = 0;
window.setInterval(function(){
$("#update").load("/game?counter=" + counter);
counter++;
}, 5000)
views.py
from flask import request
#app.route("/game")
def live_game():
textlist = ['a','b','c','d']
counter = request.args.get('counter')
return "<p> " + textlist[counter] + " </p>"
I found this in a previous post. What I would like to do is update utilize this method in updating some cool justgage that I found online to show the most up to date temperature and humidity readings from my database. Here is the script that I was wanting to use:
HTML
<div class="container">
<div class="jumbotron">
<h1>Historical Environmental Readings</h1>
<div class="container-fluid" id="dht-container">
<div id="g1" style="width: 200px; height: 150px;"></div>
<div id="g2" style="width: 200px; height: 150px;"></div>
</div>
</div>
</div>
.....
<script>
function ajaxd(NodeID) {
//reload result into element with id "dht-container"
$(??????).load("/tempnodeDHT", function() { alert( "Temp Load was performed." ); });
document.addEventListener("DOMContentLoaded", function (event) {
var g1 = new JustGage({
id: "g1",
value: 50,
min: -20,
max: 150,
title: "DHT Temp",
label: "temperature",
pointer: true,
textRenderer: function (val) {
if (val < NODE_EnvCP.low_temp) {
return 'Cold';
} else if (val > NODE_EnvCP.hot) {
return 'Hot';
} else if (val === NODE_EnvCP.optimum_temp) {
return 'OK';
}
},
});
var g2 = new JustGage({
id: "g2",
value: 50,
min: 0,
max: 100,
title: "Target",
label: "Humidity",
pointer: true,
textRenderer: function (val) {
if (val < NODE_EnvCP.low_hum) {
return 'LOW';
} else if (val > NODE_EnvCP.high_hum) {
return 'HIGH';
} else if (val === NODE_EnvCP.optimum_hum) {
return 'OK';
}
},
});
setInterval(function () {
(currentTemp, currentHumidity)=ajaxd();
g1.refresh(currentTemp);
g2.refresh(currentHumidity);
return false;
}, 2500);
});
</script>
This is my python flask function:
run.py
#app.route('/nodeDHT')
def getLatestDHT():
NodeID = request.args.get('NodeID')
df = DAO.Pull_CURRENT_DHT_Node_Data(self, NodeID)
currentTemp = df.Temperature[0]
currentHumidity = df.Humidity[0]
return (currentTemp, currentHumidity)
I was hoping that I could change the ?????? inside
$(??????).load("/nodeDHT", function() { alert( "Temp Load was performed." ); });
so that the two variables (currentTemp, currentHumidity) would end up back into the javascript portion so that the gages would update every 2.5 seconds. Also, am I passing the variable back to the python flask? there is a variable already pushed to the html when it was rendered.
EDIT:
could I do something like this:
#app.route('/nodeDHT')
def getLatestDHT():
NodeID = request.args.get('NodeID')
df = DAO.Pull_CURRENT_DHT_Node_Data(self, NodeID)
currentTemp = df.Temperature[0]
currentHumidity = df.Humidity[0]
return json.dumps(currentTemp, currentHumidity)
and in the javascript side do something like this?
function ajaxd(NodeID) {
//reload result into javascript
$.get("/nodeDHT",function( currentTemp, currentHumidity ){ console.log($.parseJSON(currentTemp, currentHumidity)});
What I'm really asking is. How can I pass single/multiple variables to the python flask function from the javascript function and then get back a dataframe where I can use column values to update a chart or multiple variables back to the javascript function to be used in a setinterval to be used for multiple functions such as updating justgage
setInterval(function () {
(currentTemp, currentHumidity)=ajaxd();
g1.refresh(currentTemp);
g2.refresh(currentHumidity);
return false;
}, 2500);
---------------------DOUBLE EDIT -----------------------
COULD I DO SOMETHING LIKE THIS:
function UPDATEGAGES(NodeID) {
$.get('/nodeDHT?NodeID='+NodeID+'&startdatetime='+startdatetime,
function(data){ const parsed = JSON.parse(data)};
g1.refresh(currentTemp);
g2.refresh(currentHumidity);
});
setInterval(function () {
UPDATEGAGES(NodeID);
return false;
}, 2500);
If you want to send variables to server in get method, use variables in url
'/tempnodeDHT?NodeID='+your_nod_id+'&anotherVar='+value+'&anotherVar2='+value2
You can access them in your flask server as below
NodeID = request.args['NodeID']
anotherVar = request.args['anotherVar']
anotherVar2 = request.args['anotherVar2']
If you want to send multiple variables from flask server to your front end, send it as JSON
return jsonify({'currentTemp': currentTemp, 'currentHumidity': currentHumidity })
When you handle it the response from the server, again parses it to JSON.
$.get( '/nodeDHT/tempnodeDHT?NodeID='+your_nod_id+'&anotherVar='+value+'&anotherVar2='+value2, function( data ) {
const parsed = JSON.parse(data)
// here you can access your 'currentTemp' variable from parsed.currentTemp
});
EDIT
For your final desired output
function UPDATEGAGES(NodeID, startdatetime) {
$.get('/nodeDHT?NodeID='+NodeID+'&startdatetime='+startdatetime,
function(data){
const parsed = JSON.parse(data)
g1.refresh(parsed.currentTemp);
g2.refresh(parsed.currentHumidity);
};
)
};
setInterval(function () {
UPDATEGAGES(NodeID, startdatetime);
return false;
}, 2500);

Fullcalendar 3 change draggable events when changing week

I work with fullcalendar 3 with laravel.
The draggable events are courses and should be different every week. I want to dynamically change the courses when I change the week in the calendar.
At the moment in the controller I have a function that give me every course:
public function index()
{
$corsi = Corso::select('titolo', 'descrizione','ore_45esimi')->get();
return view('lezione.calendario_lezioni')->with(array('corsi' => $corsi));
}
then in the view I display the events using a div:
<div id="external-events">
#foreach($corsi as $corso)
<div class="external-event bg-formazione">{{$corso->titolo }}
<br>
<div style="font-size: small">{{$corso->descrizione }} </div>
<input id="ore" type="hidden" value="{{$corso->ore_45esimi }}">
</div>
#endforeach
</div>
And in the Fullcalendar js file I have a function to make the courses draggable:
function ini_events(ele) {
ele.each(function () {
let eventObject = {
title: $(this).contents()
.filter(function () {
return !!$.trim(this.innerHTML || this.data);
})
.first().text(),
descrizione: $.trim($(this).contents()[3].firstChild.textContent),
ore: $(this).contents('#ore').val(),
color: $(this).css("background-color"),
};
$(this).data('event', eventObject);
$(this).draggable({
zIndex: 1070,
revert: true,
revertDuration: 0
});
});
}
ini_events($('#external-events div.external-event'));
I found the viewRender function that allow me to get the begin and the end of the displayed week:
$('#calendar').fullCalendar({
...
viewRender: function (element) {
var start = moment(element.intervalStart).format();
var end = moment(element.intervalEnd).subtract(1, 'd').format();
},
});
How can I use the start and end variable into the index method in the controller's query when I first show the calendar and every time I change the week?
You wish to pass two javascripts variables in php. There is huge literature on this issue, see for example
Laravel blade pass Javascript variable in php
There are many possible solutions.
I prefer pass the values of the variables through an url to a new method and after through session to the index method.
1) routes/web.php
Route::get('yourproject/{start}/{end}/getstartandend','yourController#getstartandend');
2) view
$('#calendar').fullCalendar({
...
viewRender: function (element) {
var start = moment(element.intervalStart).format();
var end = moment(element.intervalEnd).subtract(1, 'd').format();
},
});
...
appBase="{!!URL::to('/')!!}";
var route = appBase + "/yourproject/"+start+"/"+end+"/getstartandend";
$.get(route);
3) yourController
public function index ()
{
$corsi = Corso::select('titolo', 'descrizione','ore_45esimi')->get();
return view('lezione.calendario_lezioni')->with(array('corsi' => $corsi));
$start = session('start');
$end = session('end');
....
}
public function getstartandend ($start, $end)
{
session(['start' => $start]);
session(['end' => $end]);
}

How can I kill all my functions after execution?

I have a condition column == 1 and if this is the case, the function MakeCellsEditable and the function myCallbackFunction are initialized:
<script src="https://raw.githubusercontent.com/ejbeaty/CellEdit/master/js/dataTables.cellEdit.js"></script>
$(document).ready(function () {
var table = $('#myTable').DataTable();
$('#myTable tbody').on('mousedown', 'td', function () {
$('#myTable').data('column', table.cell(this).index().columnVisible);
});
if (column == 1) {
table.MakeCellsEditable({
"onUpdate": myCallbackFunction
});
}
});
function myCallbackFunction(updatedCell, updatedRow, oldValue) {
var array = updatedRow.data();
var id = array[0];
var column = $('#myTable').data('column');
console.log("The column is: " + column);
jQuery.ajax({
type: "POST",
url: "update.php",
data: {
updatedCell: updatedCell.data(),
id: id,
column: column,
},
cache: false
});
}
What I want to do is, after the functions are executed, I want to kill them. Because otherwise if I one time clicked column 1, then all my tables are editable (not only column 1).
I tried table.unbind(); or table.die(), but this didn't work out.
I tested at the end of the code:
function destroyTable() {
if ($.fn.DataTable.isDataTable('#myTable')) {
table.destroy();
table.MakeCellsEditable("destroy");
}
}
But it didn't work out
To answer the question in the headline: Yep:
function thiswilljustworkonce(){
alert("once");
this.thiswilljustworkonce=function(){};
}
thiswilljustworkonce();
thiswilljustworkonce();
Use columns option for CellEdit plugin to specify which column needs to be editable. There would be no need to remove event handler.
var table = $('#example').DataTable();
function myCallbackFunction (updatedCell, updatedRow, oldValue) {
console.log("The new value for the cell is: " + updatedCell.data());
console.log("The values for each cell in that row are: " + updatedRow.data());
}
table.MakeCellsEditable({
"columns": [0],
"onUpdate": myCallbackFunction,
"confirmationButton": true
});
See this example for code and demonstration.

Javascript not working when Alert is removed

I use D3.js and upon loading data from csv file the page isn't rendering when I remove the alert() statements. I;'m not a js specialist and I know it's something to do with asynchronous modes of operation but I don't know what to change.
when alert("AAAAAAAA"); is removed it works I appreciate this is a bespoke
issue so the other posts on the subject were not easily understood.
Many Thanks
Andy
</style>
<div id='dashboard2' align="center"></div>
<div id='dashboard' align="center"></div>
<script src="/xxxxxxxx/templates/uber/js/d3.min.js"></script>
<script type="text/javascript">
var climate_csv = function()
{
d3.csv("/xxxxxxxx/templates/uber/js/theclimate.csv", function(climate_statistics)
{
//prices is an array of json objects containing the data in from the csv
console.log("climate_statistics:", climate_statistics)
climate_data = climate_statistics.map(function(d)
{
//each d is one line of the csv file represented as a json object
console.log("d", d)
month = d.month;
console.log("month:", d.month, month)
low = +d.low;
console.log("low:", d.low, low)
high = +d.high;
console.log("high:", d.high, high)
rainfall = +d.rainfall;
console.log("rainfall:", d.rainfall, rainfall)
sunshine = +d.sunshine;
console.log("sunshine:", d.sunshine, sunshine)
nighttime = +d.nighttime;
console.log("nighttime:", d.nighttime, nighttime);
return {"Month": month, "cStats": {"low": low , "high": high} , "rainfall": rainfall , "sun":{"Sunshine": sunshine , "Nighttime": nighttime}}
})
})
}
</script>
<script type="text/javascript">
var climateStats2=[
{TempRange:'Low',cStats:{low:0}}
];
var climateStats3=[
{TempRange3:'High',cStats:{high:0}}
];
var climateStats4=[
{TempRange4:'Rainfall',cStats:{rainfall:0}}
];
var climateStats5=[
{TempRange4:'Rainfall',cStats5:{lower5:0, upper5:0}}
];
climate_csv();
alert("AAAAAAAA");
dashboard('#dashboard',climate_data,climateStats2,climateStats3,climateStats4,climateStats5);
Seems like your data is not fully loaded, when you call dashboard. It works with the alert because while the alert is open, your script is paused. Another thing is, that you are using global variables here. Let's avoid this using callbacks.
D3's csv function uses a callback and calls it, when the data is ready.
d3.csv("/xxxxxxxx/templates/uber/js/theclimate.csv", function(climate_statistics) {
/* ... */
});
You can now either call the dashboard function inside the callback, or add a callback to your function. Let's do the latter here:
var climate_csv = function( callback ) {
d3.csv(
"/xxxxxxxx/templates/uber/js/theclimate.csv",
function( climate_statistics ) {
var climate_data = climate_statistics.map(function( d ) {
month = d.month;
low = +d.low;
high = +d.high;
rainfall = +d.rainfall;
sunshine = +d.sunshine;
nighttime = +d.nighttime;
return {
"Month": month,
"cStats": {
"low": low,
"high": high
},
"rainfall": rainfall,
"sun": {
"Sunshine": sunshine,
"Nighttime": nighttime
}
};
});
// we are done with mapping our data
// let's call the callback with the data
callback(climate_data);
});
};
/* ... */
climate_csv(function( climate_data ) {
dashboard('#dashboard', climate_data, climateStats2, climateStats3,
climateStats4, climateStats5);
});
Put the function that is not working when you remove the alert inside the success callback, that will make the trick.
.csv works async, so when you put the alert, the request is completed on the background, when you remove it no "wait time" is added (as it should be) and that's why it's not working.
Not using d3.js, but this doc could help:
https://github.com/mbostock/d3/wiki/CSV
d3.csv("path/to/file.csv")
.row(function(d) { return {key: d.key, value: +d.value}; })
.get(function(error, rows) { console.log(rows); });
Hope it helps.

Images in JSON AngularJS

I'm new to AngularJS, so sometimes when I do some mistake that is obvious, I still can't figure out what is going wrong with my code. So saying, here is my doubt:
HTML code:
<body ng-controller = "Ctrl">
<script id="Page6.html" type="text/ng-template">
<div class="list card" style="background-color: beige">
<div class="item item-icon-left">
<i class="icon ion-home"></i>
<input type="text" placeholder = "Enter display name" ng-model="user.nam">
</div>
<a ng-click = "saveedit(user)"<button class="button button-clear">SAVE DETAILS</button></a>
</div>
</script>
</body>
CONTROLLER.JS
.controller('Ctrl',function($scope,$rootScope,ContactService){
$rootScope.saveedit=function(user) {
ContactService.save({names: user.nam, image:"images.jpg"},ContactService.getid("Donkey"));
}
});
THIS IS THE SERVICE:
.service('ContactService', function () {
var items = [
{ id: 1, names: 'Dolphin', image: 'dolphin.jpg',}, { id: 2, names: 'Donkey', image: 'donkey.jpg'}, { id: 3, empid: 'FG2043', image: 'penguin.jpg'}];
var im = [{image: ''}];
var ctr=0;
var uid=3;
this.save = function (contact,id) {
ctr=0;
for (i=0;i<items.length;i++) {
if(items[i].id == id)
{
im[0].image= items[i].image;
ctr=100;
break;
}
}
uid = (uid+1);
contact.id = uid;
items.push(contact);
if (ctr==100 ) {
alert("in save putting the image");
items[contact.id].image = im[0].image; //doubt
alert("finished putting image");
}
}
//simply search items list for given id
//and returns the object if found
this.getid = function (name) {
for (i=0;i<items.length;i++) {
if (items[i].names == name) {
return (i+1);
}
}
}
//simply returns the items list
this.list = function () {
return items;
}
});
The problem I am facing is this: Everything works, except one thing. In ContactService, push() function, the line I have commented as //doubt is not getting executed.
The alert before it "in save putting the image" runs, but the alert "finished putting image" doesn't. What is the mistake there??
The problem here is that you're using the id's, which start at 1, to navigate in an array whose indexes start at 0.
To access the most recently pushed element, you should rather do :
items[contact.id - 1].image = im[0].image;
But you actually don't need to access the array : items[contact.id - 1] will return the object that you just pushed, and which is already referenced by variable contact, so you could just do :
contact.image = im[0].image;

Categories