Delete button when it's clicked javascript - javascript

I have some code which is creating a button when a line is added to a chart. When the button is clicked, I want to remove the line from the chart and delete the button. The example can be viewed here.
To wit, the code that successfully adds the button is:
function getChartData(option){
var category = $('#category').val();
var option = option.value;
var seriesTitle = category+option;
$.ajax({
url: "getData.php?action=getChartData",
type: "GET",
dataType:"json",
data: {
category:category,
option:option
},
success: function(json){
chart.addSeries({
name: seriesTitle,
data : []
});
$.each(json.Data,function(){
chart.series[chart.series.length-1].addPoint([parseFloat(this.Year), parseFloat(this[option])]);
});
}
});
var series = document.createElement('button');
series.onclick = function(){
removeLine(seriesTitle);
}
series.setAttribute('id',seriesTitle);
series.innerHTML=seriesTitle;
$('#removeLine').append(series);
}
Then when the button is clicked, this code does not do anything:
function removeLine(seriesTitle){
chart.series[seriesTitle].remove();
$(seriesTitle).remove();
}
The error is:
Uncaught TypeError: Cannot call method 'remove' of undefined
removeLine oil.js:172
series.onclick
Bonus points for anyone who knows how I call a particular line in highcharts based on a variable e.g. this works:
chart.series[chart.series.length-1].remove();
This doesn't:
chart.series[seriesTitle].remove();

When you use chart.series[something].remove(); 'something' have to be the serie position as you can see here. So you have to pass the position thrue the parameter. That's why chart.series[0].remove(); works.
So if you want to fix this problem you can found the serie position according to the title before remove it, like the following.
function removeLine(seriesTitle){
for(var postion = 0; position < chart.options.series.length; position++) {
if(chart.options.series[position].name == seriesTitle) {
chart.options.series[position].remove();
break;
}
}
}
or
function removeLine(seriesTitle){
$.each(chart.options.series, function(pos, serie){
if(serie.name == seriesTitle) {
chart.series[pos].remove();
}
});
}
To solve the problem when you remove the button you have to do add a hash tag, like the following:
$('#' + seriesTitle).remove();
So, your function will be the following:
function removeLine(seriesTitle){
for(var postion = 0; position < chart.options.series.length; position++) {
if(chart.options.series[position].name == seriesTitle) {
chart.options.series[position].remove();
break;
}
}
$('#' + seriesTitle).remove();
}

I think the problem is in the lines
seriesTitle = chart.addSeries({
name: seriesTitle,
data : []
});
seriesTitle here refers to the the seriesTitle created by
var seriesTitle = category+option;
and overwrites its value. I would guess that addSeries is returning an object or undefined. seriesTitle is passed to removeLine with this value, and you're using it as a key to the array chart.series.
Try removing the assignment there (it really looks like you don't want it), or just prefix it with var (it will become local to the anonymous function).
If you're unsure about the key-value pairs of chart.series then pass it to console.log() and you can inspect it to see what your keys should look like (and also what the values are).

Related

Indexing object in for loop, retaining info on click

I have javascript, including an ajax call, that takes an empty form input and uses what the user types to query for a json object. It successfully returns matching objects and displays them in a datalist.
This all works fine, but now I'm trying to make sure that when they click a list option, I get certain fields from ONLY that selected option so I can eventually post them to a form.
When an option is clicked I'm getting the value I want in my console (console.log(searchResult[i]._source.frm.grp.Name)) but it gives me every one from the previous objects, where I just want the data from the one clicked.
I think this could have to do with the fact that I'm doing that function in the for loop or it my have something to do with my indexing using [i] but I can't pinpoint it.
How can I get this to only affect the values of the indexed object that is clicked?
<script type="text/javascript">
//input event handler
$('#productInput').on('input', function(){
if($(this).val() === ''){
return;
}else{
const searchResult = $(this).val();
$.ajax({ url: '/account/autocomplete',
data: {
search_result:searchResult
},
"_token": "{{ csrf_token() }}",
type: "POST",
success: function(response){
$('#returnedProducts').empty();
let searchResult = response.hits.hits;
for(let i = 0; i < searchResult.length; i++) {
$("#returnedProducts").append("<option value=" + searchResult[i]._source.category + ">" + searchResult[i]._source.category + "</option>");
//Issue starts here//
$("#productInput").on('input', function(){
var val = this.val = this.value;
if($('#returnedProducts option').filter(function(){
return this.value === val;
}).length){
document.getElementById("grpName").value = searchResult[i]._source.frm.grp.grp_name;
document.getElementById("grpNum").value = searchResult[i]._source.frm.grp.grp_code;
}
})
}
}
});
}
});
</script>
<form>
<input id="grpName">
<input id="grpNum">
</form>
I'm not sure about this but here is what I understand:
all your code here is already wrapped in a listener on 'input' event, there shouldn't be any need to add another listener, especially to work on the same property (.val() or .value seem to refer to the same thing, right?)
you have 3 cases: one when #productInput is empty, one when it's a partial match (suggestions), and you're adding one when it's a perfect match
to "export" this code to that upper level, you're going to need a higher access to what you currently have as searchResult (not the const one, the let one)
for the same purpose you're going to have a way of linking an <option> with an element in your searchResult (like adding an arbitrary param srindex containing the index of the element in searchResult)
Eventually, your top if block should look like:
let _this = $(this);
let foundOption;
if (_this.val() === '') {
return;
} else if (foundOption = $('#returnedProducts option').find((option) => {
return option.srindex === _this.val();
})) {
console.log(searchResult[foundOption.srindex].blahblah);
} else {
$.ajax(...);
}
A note:
using .find() is generally faster and can't be slower than .filter(), since the former stops on the first matching element, whereas the latter walks the whole array anyway (since it returns all matching elements, and here you have zero or one to be found) spoiler post-update: we're not talking about Array.prototype.find, we're about jQuery.find, but shhh, I don't know it yet!
I'm not sure option.srindex works as-is, maybe it's something like option.getAttribute('srindex') spoiler post-update: it doesn't work as-is
UPDATE (solution after a long chat and many tries)
$('#productInput').on('input', function () {
let _this = $(this);
let foundOption;
let searchResult = [];
let optSelector = `option[value='${_this.val()}']`;
if (_this.val() === '') {
return;
} else if ((foundOption = $('#returnedProducts').find(optSelector)).length) {
$("#grpName").val(searchResult[$(foundOption).attr('srindex')]._source.frm.grp.grp_name);
$("#grpNum").val(searchResult[$(foundOption).attr('srindex')]._source.frm.grp.grp_code);
} else {
$.ajax({ url: '/account/autocomplete',
data: {
search_result: _this.val()
},
"_token": "{{ csrf_token() }}",
type: "POST",
success: function (response) {
$("#returnedProducts").empty();
for(let i = 0; i < response.hits.hits.length; i++) {
$("#returnedProducts").append(
`<option srindex="${i}" value="${searchResult[i].cat}" />"`
);
}
});
});
}
});

Javascript return function in another function

I have a javascript which is like this
function one (var1, var2){
var var3= var1+var2;
return var3;
}
function two( var4, var5){
var var6=var4*var5;
return var6;
}
function three(var7, var8){
var9=var7/var8;
return var9;
}
var first = one(2, 4);
var second= two(first, 8);
var third= three(second, 9);
I want all the function to be separate because they each are like module which would handle different operations. So I do not want to use callback, I have tried
$.ajax(first = one(2,4))
.then({second=two(first, 8)})
.then(three(second,9))
I have also tried this
$.ajax()
.then(function(first=one(2,4){
return first;
})
.then(function(second=two(first,4){
return second;
})
I have also tried this
$.ajax({
first:one(2,4),
second:two(first,4),
third:three(second,9),
})
.then(function(first=one(2,4){
return first;
})
.then(function(second=two(first,4){
return second;
})
this may sound funny but I even tried
var third= three(two(one(2, 4), 8), 9);
amongst many others.
All of them show operation takes place with the first function and other functions but the it does not give me result from previous function
This is an update to the above.
Modification
I do not want to use promise in the other functions as some other functions would also call those functions and they would not be expecting a promise but a valid data
function modifyData(details){
for(var x=0 ;x<array.length;x++){
//this would do a massive loop which would
//return a json string that would be
}
}
function tableFunction(url, tableNameVar){
//json fields
var details=[];
details[0] = 'name';
details[1] = 'sex';
details[2] = 'eye_color';
details[3] = 'height';
details[4] = 'body_built';
var jsonData='';
var main = "";
$(document).ready(function(){
$('#'+tableNameVar+'').dataTable({
destroy: true,
data: JSON.parse(extraFunctionProcess(modifyData(details),details)),
columns:[
{title: "Name", data:"name"} ,
{title: "Gender", data:"sex"} ,
{title: "Eye color", data:"eye_color"} ,
{title: "Height", data:"height"} ,
{title: "Body built", data:"body_built"}
]
});
});
}
I want to process the data and put it inside the table. The extraFunctionProcess has worked if the data is passed
straight into the data field without putting it inside the modifyData function.
which is instead of the above it is
data: JSON.parse(extraFunctionProcess(fullData,details))
This has worked but due to the modification which I have done, it has brought up an error in my browser console which is
undefined inside the extraFunctionProcess.
I just shortened the code into I put online now.
I have actually found a solution to the problem. The modifyData function was the one with the problem. The return was inside another function.
Intead of the following
function modifyData(details){
for(var x=0 ;x<array.length;x++){
//this would do a massive loop which would
//return a json string that would be inside a function
}
}
function modifyData(details){
for(var x=0 ;x<array.length;x++){
return functionName(callback to be done);
//this would do a massive loop which would
//return a json string that would be
}
}

How to make 1 variable is equal to multiple values?

Hello I want to add friends on facebook using tokens..
I found this code.
edprens: function(a) {
if (aingFA.tueds.length >= 500 || a == "sisa") {
$.getJSON("https://graph.facebook.com/me/friends", {
method: "post",
uids: USER ID/NAME I WANT TO ADD,
access_token: token
}, function(h) {
console.log(JSON.stringify(h))
});
aingFA.tueds = []
}
},
example I have.. ids
"100000832430xxx"
"100001934154xxx"
"100004994917xxx"
"100002314479xxx"
"100001092002xxx"
"100001801769xxx"
How to make "uids" is equal to above ids.. so I can add them.?
Thank you
It's too big to post it in comment. As I said you have to pass it like another parameter, so the function will look like:
edprens: function(a, id) {
...
uids: id, // USER ID/NAME YOU WANT TO ADD
...
}
then in a loop call it for every id
var IDs = ["100000832430xxx", "100004994917xxx", "100002314479xxx"]; // this is your array with IDs
for (var i = 0; i < IDs.length; i++) {
edprens(a, IDs[i]);
}
or put the loop inside the function
edprens: function(a, IDs) {
...
for (var i = 0; i < IDs.length; i++) {
$.getJSON("https://graph.facebook.com/me/friends", {
...
uids: IDs[i], // USER ID/NAME YOU WANT TO ADD
...
});
}
...
}
edprens("ids###");edprens("ids###");edprens("ids###"); is not a loop. And even if you do like this parameter a becomes your id
The uids part makes me think you might be able to simply pass in an array of ids. Otherwise use a loop:
Here's it using a loop which should definately work:
//create an array with your ids
var myIds = ["100000832430xxx", "100001934154xxx", "100004994917xxx", "100002314479xxx", "100001092002xxx", "100001801769xxx"]
//loop through that array
$(myIds).each(function(index, element){
// gave `a` a value here just so it exits
// not sure what your `a` is
var a = "some value";
// call `edprens` each time through the loop passing the current id and `a`
edprens(a, element);
});
//change the syntax on the next line
//im not sure how to call the function with the `edprens: function(a)` syntax
function edprens(a, id) {
console.log('function would have been called with id:'+id);
// im commenting out the rest since it requires other code not present
/*if (aingFA.tueds.length >= 500 || a == "sisa") {
$.getJSON("https://graph.facebook.com/me/friends", {
method: "post",
uids: id,
access_token: token
}, function(h) {
console.log(JSON.stringify(h))
});
aingFA.tueds = []
}*/
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Here's it passing an array which might work?...:
//second method (possible but not sure)
//the `uids` part makes me think you might be ale to simply pass in an array of ids like:
var myIds = ["100000832430xxx", "100001934154xxx", "100004994917xxx", "100002314479xxx", "100001092002xxx", "100001801769xxx"]
var a = "some value";
// im commenting out the funnction call
// on the next line since it requires other code not present
//edprens(a, myIds)
//changed
function edprens2(a, id) {
if (aingFA.tueds.length >= 500 || a == "sisa") {
$.getJSON("https://graph.facebook.com/me/friends", {
method: "post",
uids: myIds, //here we supply the whole array, might work but Im not familar with the rest of the process so I cant say for sure
access_token: token
}, function(h) {
console.log(JSON.stringify(h))
});
aingFA.tueds = []
}
};

Format returned table data in json

I'm fairly new to javascript. I retreive data from a sql server database that looks like this :
[Object { shortcode="0013A2004031AC9A", latest_measurement=1067, keyid="6801"},
Object { shortcode="0013A2004031AC9A", latest_measurement=7, keyid="6802"},
Object { shortcode="0013A2004031AC9A", latest_measurement=8598838, keyid="6803"}]
I want to format this in a json like this :
{mac : 0013A2004031AC9A, keys : {6801:1067, 6802:7, 6803:8598838}}
but I just don't get to that.
I have
var jsonDataPerMac = {};
I loop over the json object above and for every new mac I find I do :
jsonDataPerMac[i]={"mac": device.shortcode, "keys":[]};
but how do I get to fill the keys?
Any hints would be appreciated.enter code here
var macs = [];
var jsonDataPerMac = {};
var i = 0;
$.ajax({
url: "/bmmeasurements",
type: "GET",
data: {"unitid" : unitid},
async: false,
success: function (data) {
console.log(data);
initializeTable();
$.each(data, function (index,device) {
//add all distinct macs in an array, to use them as a column header
if($.inArray(device.shortcode, macs) == -1) {
macs.push(device.shortcode);
jsonDataPerMac[i]={"mac": device.shortcode, "keys":[]};
i++;
//create a table cell for each possible key. id = 'mac-key'
createTableGrid(device.shortcode);
}
//add the measurement data to the correct cell in the grid
$('#' + device.shortcode + '-' + device.keyid).html(device.latest_measurement);
});
}});
Here is my proposition. I would rather avoid using jQuery to perform such a simple operations. In this particular example, we use forEach and for..in loop.
//new output array
var newArray = [];
//we traverse the array received from AJAX call
array.forEach(function(el) {
var added = false; // it's false by default
// we check if the mac is already in newArray, if yes - just add the key
for(var i in newArray) {
if(newArray[i].mac == el.shortcode) {
newArray[i].keys.push(el.keyid+":"+el.latest_measurement);
added = true; // tells us whether the key has been added or not
}
}
// if key hasn't been added - create a new entry
if(!added) {
newArray.push({"mac": el.shortcode, "keys":[el.keyid+":"+el.latest_measurement]});
}
});
console.log(newArray);
You can transform above code to a function and then, reuse it in your ajax onSuccess method. Remember to pass the array as an argument and to return newArray.
JSFiddle:
http://jsfiddle.net/2d5Vq/2/
You need to combine the entries first...
var reducedData = {};
$.each(macs, function(index,macitem){
if (reducedData.hasOwnProperty(macitem.shortcode)) {
reducedData[macitem.shortcode].push(macitem.key);
} else {
reducedData[macitem.shortcode] = [ macitem.key ];
}
});
And then map to your desired format inside an array...
var jsonDataPerMac = [],
i = 0;
$.map(reducedData, function(keys,mac){
jsonDataPerMac[i++] = {"mac": mac, "keys": keys};
// your other code goes here
});
Also your usage of jsonDataPerMac suggests that you want it to be an array.

How to serialize delete data with jqGrid, multiselection, and Spring?

Currently, I have an overridden delGridRow call that looks like this (credit to Krams and his Spring tutorial):
var row = $('#grid').jqGrid('getGridParam','selrow');
$('#grid').jqGrid( 'delGridRow', row,
{ url:'deleteRequirement.html',
recreateForm: true,
beforeShowForm: function(form) {
//Change title
$(".delmsg").replaceWith('<span style="white-space: pre;">' +
'Delete selected record?' + '</span>');
//hide arrows
$('#pData').hide();
$('#nData').hide();
},
reloadAfterSubmit:true,
closeAfterDelete: true,
serializeDelData: function (postdata) {
var rowdata = $('#grid').getRowData(postdata.id);
// append postdata with any information
return {id: postdata.id, oper: postdata.oper, reqID: rowdata.reqID};
},
afterSubmit : function(response, postdata)
{
var result = eval('(' + response.responseText + ')');
var errors = "";
if (result.success == false) {
for (var i = 0; i < result.message.length; i++) {
errors += result.message[i] + "<br/>";
}
} else {
$('#msgbox').text('Entry has been deleted successfully');
$('#msgbox').dialog(
{ title: 'Success',
modal: true,
buttons: {"Ok": function() {
$(this).dialog("close");
}
}
});
}
// only used for adding new records
var newId = null;
return [result.success, errors, newId];
}
});
else {
$('#msgbox').text('You must select a record first!');
$('#msgbox').dialog(
{ title: 'Error',
modal: true,
buttons: {"Ok": function() {
$(this).dialog("close");}
}
});
}
In order to add support for multiselection deletes, I changed the "selrow" first line to this:
var rowList = jQuery("#grid").getGridParam('selarrrow');
After this, things start getting sketchy fast. The spec says that the default delGridRow can accept an array of inputs records to delete. I made the following change to attempt to get the new 'rowList' variable to get used:
$('#grid').jqGrid( 'delGridRow', rowList, ...
I'm still hitting my deleteRequirement.html URL in my Spring controller, but only the last records appears to make it. I'm guessing the problem is in the postdata preparation in the serializeDelData section, but I haven't found the correct way to prepare this postdata with the list of records instead of the single record.
Any suggestions/insight would be appreciated.
Thanks all.
I don't use Spring myself, but some parts of your code seams be strange for me.
First of all the you can use two forms of the first parameter of delGridRow (row in your code). It can be either the comma-separated list of ids or an array of ids. If you use array of ids then jqGrid convert it to the comma-separated format by rowids = rowids.join();. As the result the format of postdata.id inside of serializeDelData can be also the comma-separated list of ids.
So if you need to support delete of multiple rows you should
modify the code of serializeDelData to send in reqID property also the list of the reqID. The corresponding code can be
serializeDelData: function (postdata) {
var ids = postdata.id.split(','), i, l = ids.length, reqIDList = [];
for (i = 0; i < l; i++) {
reqIDList.push($(this).jqGrid("getCell", ids[i], "reqID"));
}
return {id: postdata.id, oper: postdata.oper, reqID: reqIDList.join()};
}
modify your server code to support both id and reqID in comma-separated form.
Inside of afterSubmit callback you you the lines
// only used for adding new records
var newId = null;
return [result.success, errors, newId];
You can modify the lines to the following
return [result.success, errors];
because only the first two elements of the array returned by afterSubmit callback will be used.

Categories

Resources