I am working on project which using javascript to get data from database and show it in table.
Every column in the table has action column where user can (edit / delete ..etc)
When the user clicks the edit button he will be redirected to the edit page.
After he has finished the editing, he presses the backbutton on the top left of Chrome browser, to get back to the table page, but the problem is the data is not loading and the table is empty till I refresh the page, then the script code is working and data has been shown in the table.
I don't understand why is that happening, why the javascript code is not working after I click the back button
This is my code it is getting data from database and show it in the table
after calling initTable2 function
var handleISI = function() {
getData();
function getData() {
$.ajax({
async: true,
type: "GET",
url: "/admin/ISIM/GET_ISIMng",
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function(data) {
console.log(data);
data = data;
ISI.initTable2(data);
},
error: function(data) {
console.log(data);
data = [];
ISI.initTable2(data);
},
});
}
};
return {
init: function() {
// initISITable();
handleISI();
handleElements();
// handleAttributes();
handleADDISI();
},
initTable2: function(data) {
//child row delete
ISITable.find("tbody")
.find("tr.shown")
.removeClass("shown")
.next()
.remove();
//dd report check
var isDD = false;
var isDDReport = false;
if (data != undefined) {
ISITable.DataTable().destroy();
ISITable.empty();
ISITable.html("");
if (data != "") {
var thead, tbody;
thead = "<thead><tr>";
console.log(data);
$.each(data[0], function(key, value) {
if (key == "id") {} else {
thead += "<th>" + (jsTranslation[document.documentElement.lang].name) + "</th>";
}
});
(thead += "<th class='text-right'>" + (jsTranslation[document.documentElement.lang].actions) + " </th>"),
(thead += "</tr></thead>");
ISITable.append(thead);
tbody = "<tbody>";
var seq_id = 1;
for (var i = 0; i < data.length; i++) {
if (isDD) {
tbody += "<tr><td class='details-control'></td>";
} else {
tbody += "<tr>";
}
var users_id;
var name_val;
$.each(data[i], function(key, value) {
if (key == "id") {
users_id = value;
} else {
if (key == "name") {
name_val = value;
}
if (key == "username") {
tbody +=
"<td>" +
'<i class="fa fa-user" style="color: #5d56f3;"></i> ' +
value +
"</td>";
} else if (key == "totalSession") {
tbody +=
"<td>" + value.formatNumber() + "</td>";
} else {
console.log(value);
tbody += "<td>" + value + "</td>";
}
}
});
tbody +=
'<td class="text-right"><a href="javascript:;" id="attributebutton" class="btn btn-sm btn-primary btn-sm mt-1 green attribute rounded" data-toggle="tooltip" title=' +
jsTranslation[document.documentElement.lang]
.attribute +
' data-original-title="Attribute" data-id= ' +
users_id +
" data-name= " +
encodeURIComponent(name_val) +
' " ><i class="fa fa-list " style="color:white" ></i></a>';
tbody +=
' <a href="javascript:;" id="editbutton" class="btn btn-sm btn-success btn-sm mt-1 attribute rounded" data-action="Edit" data-toggle="tooltip" title=' +
jsTranslation[document.documentElement.lang].edit +
' data-original-title="Edit" data-id= ' +
users_id +
" data-name= " +
encodeURIComponent(name_val) +
' > <i class="fas fa-pencil-alt " style="color:white" ></i></a>';
tbody +=
' <a href="javascript:;" class="btn btn-sm btn-danger btn-sm mt-1 delete_isi rounded" data-action="Delete" data-toggle="tooltip" title=' +
jsTranslation[document.documentElement.lang]
.delete +
' data-original-title="Delete" data-id= ' +
users_id +
" data-name= " +
encodeURIComponent(name_val) +
' " > <i class="fas fa-trash-alt " style="color:white" ></i></a>';
tbody +=
' <a href="/admin/ISI/' +
users_id +
'" class="btn btn-sm btn-sm mt-1 btn-warning green rounded" data-action="Delete" data-toggle="tooltip" title=' +
jsTranslation[document.documentElement.lang]
.manage +
' data-original-title="Manage" data-id= ' +
users_id +
" data-name= " +
encodeURIComponent(name_val) +
' " > <i class="fa fa-globe " style="color:white" ></i></a> ';
tbody += "</td>";
tbody += "</tr>";
seq_id++;
}
tbody += "</tbody>";
tbody += " ";
ISITable.append(tbody);
}
}
$(document).ready(function() {
$('[data-toggle="tooltip"]').tooltip();
});
var table = ISITable;
// var columnDefs = [{ className: "text-left", targets: "_all" }];
if (data == undefined) {
// columnDefs = [{ className: "dt-center", targets: "_all" }];
}
var oTable = table.DataTable({
destroy: true,
ordering: false,
paging: true,
lengthMenu: [
[5, 10, 15, 20, -1],
[5, 10, 15, 20, "All"], // change per page values here
],
pageLength: 10,
dom: "<'row' <'col-md-12'T>><'row'<'col-md-9 col-sm-12 topLenght'l><'col-md-3 col-sm-12'f>r><'table-scrollable't><'row'<'col-md-5 col-sm-12'i><'col-md-7 col-sm-12'p>>",
// columnDefs: columnDefs,
language: $.fn.dataTable.language,
className: "dt-center",
language: {
url: window.location.origin + "/i18N/" + document.documentElement.lang + ".json",
},
});
//Top lenght selector
var x = 10;
if (x == "") {
x = "10";
}
var optionhtml = "";
if (x == "10") {
optionhtml += "<option selected value='10'>10</option>";
} else {
optionhtml += "<option value='10'>10</option>";
}
if (x == "20") {
optionhtml += "<option selected value='20'>20</option>";
} else {
optionhtml += "<option value='20'>20</option>";
}
if (x == "30") {
optionhtml += "<option selected value='30'>30</option>";
} else {
optionhtml += "<option value='30'>30</option>";
}
var xx = " ";
//top kutusunu taşır.
$("#reporttable_wrapper").find(".topLenght").append(xx);
},
};
})();
jQuery(document).ready(function() {
ISI.init(); // init metronic core componets
});
I see that this is a metronic table. I have worked on a metronic website, are you using the regular JS version? I can't tell which one you are using.
I have used the Angular version and have had this problem occur when there was an asynchronous process inside a synchronous function.
From looking at the code, I can't see what the functions, handleISI(), handleElements(), handleADDISI() do so I cannot comment on them. I tried searching a few snippets on the latest metronic version, and couldn't find them. If you are using a pre v7 version, please let me know.
After all that, looking at the code you have given me, there are only two things that stand out to me
The init function is synchronous and your ajax call is async. Meaning that your handlers get initiated before the data is retrieved. Which may or may not be the cause of your problem. You haven't shared the edit action either, I will have to assume that the edit action might not be adding the data locally and only on the server, which means that your table might be getting initialized before the new data call comes since the variable data is shared. Remember, even the put request takes a little bit of time.
Turning the process async using promises might fix your problem.
You are using the back button on chrome. If you don't force update on refresh, then there is a high chance that a cached version is being served to you and refreshing makes chrome fetch again.
You will have to share more code with us to get a more accurate answer. If I have completely missed the edit action being handled in the given code, please let me know where.
Related
I want to delete the element of the list by clicking the delete button.
i have written the following ajax call for this:
.ajax({
type : "GET",
url : 'getVenueList',
success : function(data) {
console.log(data);
var sequenceNo = 1;
var tableData = '';
for (var i = 0; i < data.length; i++) {
tableData = "<tr><td>" + sequenceNo + "</td><td>"
+ data[i].venueName + "</td>";
tableData += ' <td><a class="no-line"> <i id="Edit" title="Edit" class="fa fa-pencil-square-o" style="font-size: 15px;" aria-hidden="true"></i></a> </td>';
tableData += ' <td><a class="no-line" onclick="deleteVenue(this);"> <span class="glyphicon glyphicon-remove" style="color: red" ></span></a></td>';
tableData += ' <td style="display: none;"> '
+ data[i].venueId + '</td></tr>';
sequenceNo = sequenceNo + 1;
$('#tbodyId').append(tableData);
}
}
});
on delete icon i have put the onclick function :
function deleteVenue(obj) {
var setValue = obj.id;
$
.ajax({
type : "GET",
async : false,
url : "deleteVenue",
data : {
venueId : setValue
},
success : function(data) {
console.log(data);
window.location.reload();
}
});
}
but the issue is i am not getting the id in obj...
what is the solution?
You should change this part.
<a class="no-line" onclick="deleteVenue(this);">
to
<a class="no-line" onclick="deleteVenue('+ data[i].venueId + ');">
function deleteVenue(id) {
$.ajax({
type : "GET",
async : false,
url : "deleteVenue",
data : {
venueId : id
},
success : function(data) {
console.log(data);
window.location.reload();
}
});
}
I am creating a table using Ajax and JavaScript and using Spring Boot as a backend technology. So the scenario is:
There are two dropdowns one for selecting company name from list and with that company, corresponding truck list would be displayed. After selecting company name and truck from both the dropdowns, clicking on search button there would display a table with dynamic data of selected company and truck. So, for each created row there is select drop down in table row. So I want to display further data when selecting any of the option list from dropdown.
I want to display child row inside parent row after selecting any of the option from dropdown list using Ajax and JavaScript.
Below is my script where I am creating table with dynamic data:
function searchdata(){
var companyid = $("#searchQueryDD").val();
var truckid = $("#searchtruckdd").val();
var url = "api/gettablebycompanyandtruck";
$.post(url, {
companyid : companyid,
truckid : truckid,
limit : limit,
}, function(data, status) {
if (data.status == "OK") {
if (data.statusCode == 1) {
var list = data.response;
var row = "", tripnumber="";
var newtrip = [];
var uniquetrip = {};
var row = "";
if(list.length > 0){
for(var i = 0; i < list.length; i++){
tripnumber = list[i].tripnumber;
uniquetrip[tripnumber] = list[i];
}
for(var i in uniquetrip){
newtrip.push(uniquetrip[i]);
}
for(var i = 0; i < newtrip.length; i++){
row = row + "<tr>" +
"<td>"+newtrip[i].company.companyname+"</td>" +
"<td>"+newtrip[i].driver.username+"</td>" +
"<td>"+newtrip[i].truck.name+"</td>" +
"<td>"+newtrip[i].tripnumber+"</td>" +
"<input type='hidden' id='company_id' value='"+newtrip[i].company.companyid+"'>" +
"<input type='hidden' id='trip_number' value='"+newtrip[i].tripnumber+"'>"+
"<td><select onchange='getmorerows();' id='sub_trip'>" +
"<option selected disabled>Choose subtrip</option><option value='1'>1</option>" +
"<option value='2'>2</option><option value='3'>3</option></select></td>"+
"<td>"+newtrip[i].pickupdate+"</td>" +
"<td>"+newtrip[i].deliverydate+"</td>"+
"<td>"+newtrip[i].loadrate+"</td>" +
"<td>"+newtrip[i].dispatchfee+"</td>" +
"<td>"+newtrip[i].fuel+"</td>" +
"<td>"+newtrip[i].cardfee+"</td>" +
"<td>"+newtrip[i].onroadrepair+"</td>" +
"<td>"+newtrip[i].shoprepair+"</td>" +
"<td>"+newtrip[i].trailerrent+"</td>" +
"<td>"+newtrip[i].comcheck+"</td>" +
"<td>"+newtrip[i].advance+"</td>" +
"<td>"+newtrip[i].miscellenous+"</td>" +
"<td>"+newtrip[i].total+"</td>" +
"<td>"+newtrip[i].layover+"</td>" +
"<td>"+newtrip[i].grandtotal+"</td>" +
"<td>" +
"<a data-toggle='modal' data-target='#mode_payment' onclick=\"getpayment('"+newtrip[i].tripid+"');\">"
+"<i class='fa fa-paypal' aria-hidden='true' style='color:#3585a5'></i>" +
"</a>" +
"<a onclick=\"getTrip('"+newtrip[i].tripid+"');\">"
+"<i class='fa fa-pencil-square-o ml-3' style='color: #3384a4;'></i>" +
"</a>" +
"<a href='invoice?id="+newtrip[i].tripid+"'>"
+"<i class='fa fa-file-pdf-o ml-3' aria-hidden='true' style='color:red'></i>" +
"</a>" +
"</td>" +
"</tr>";
}
}else{
row = row + "<tr><td colspan='19' style='font-size: initial;font-family: initial;'>No Data Available.</td></tr>";
}
document.getElementById('searchresulttable').innerHTML = row;
$("#triptable").css('display','inline-block');
} else {
var error = data.responseMessage;
swal(error, "", "error");
}
} else {
var error = data.responseMessage;
swal(error, "", "error");
}
});
}
And below script is to handle onchange event on select options:
function getmorerows() {
var companyid = document.getElementById("company_id").value;
var tripnumber = document.getElementById("trip_number").value;
var subtrip = document.getElementById("sub_trip").value;
var url = "api/getbysubtrip";
$.post(url,{
companyid : companyid,
tripnumber : tripnumber,
subtrip : subtrip,
},function(data, status){
if (data.status == "OK") {
if (data.statusCode == 1) {
var list = data.response;
var childrow = "";
if(list.length > 0){
for(var i = 0; i < list.length; i++){
childrow = childrow + "<tr class='display-nonee'>" +
"<td>"+list[i].company.companyname+"</td>"+
"<td>"+list[i].company.companyname+"</td>"+
"<td>"+list[i].company.companyname+"</td>"+
"</tr>";
var tr = $(this).parent().parent().nextAll(':lt(2)');
if (tr.is(".display-none")) {
tr.removeClass('display-none');
} else {
tr.addClass('display-none');
}
}
}
document.getElementById('searchresulttable').innerHTML = childrow;
} else {
var error = data.responseMessage;
swal(error, "", "error");
}
} else {
var error = data.responseMessage;
swal(error, "", "error");
}
});
}
Change one line in getmorerows()
document.getElementById('searchresulttable').innerHTML = childrow; to $('#searchresulttable').append(childrow);
I am querying a fuseki server using AJAX and the result that I am getting is a JSON object.
I would like to use pagination to go through the result with a limit of records per page. I have tried to send the JSON object to a div in the html file but it is not working. Is there a workaround this? Here is my code:
function myCallBack2(data) {
var all_results = '';
for (var i = 0; i < data.results.bindings.length; i++) {
var bc = '';
if (i % 2 == 0) {
bc = '#b8cddb';
} else {
bc = '#f2f5f7';
}
all_results += '<div class="all_results" style="background-color:' + bc + '">';
for (var j = 0; j < data.head.vars.length; j++) {
var text = data.results.bindings[i][data.head.vars[j]].value;
var type = data.results.bindings[i][data.head.vars[j]].type;
all_results += '<div class="result_row">';
if (type == ('literal')) {
all_results += '<p> ' + data.head.vars[j] + ": " + text + '</p>';
} else {
all_results += '<a href=' + text + " title=" + data.head.vars[j] + '>' + text + '</a>';
}
all_results += '</div>';
}
all_results += '</div>';
}
$('#result').html(all_results);
}
function doSparql() {
var myEndPoint = "http://localhost:3030/Test/query";
name = document.getElementById("search").value;
var requiredName = "?Author foaf:firstName \"" + name + "\".}";
myQuery = ["PREFIX dcterms: <http://purl.org/dc/terms/>",
"PREFIX foaf: <http://xmlns.com/foaf/0.1/>",
"PREFIX locah: <http://data.archiveshub.ac.uk/def/>",
"SELECT ?Register ?Id ?Date ?Type",
"WHERE{",
"?Register dcterms:creator ?Author.",
"?Register dcterms:identifier ?Id.",
"?Register dcterms:type ?Type.",
"?Register locah:dateCreatedAccumulatedString ?Date.",
requiredName
].join(" ");
console.log('myQuery: ' + myQuery);
window.alert(myQuery);
$.ajax({
dataType: "jsonp",
url: myEndPoint,
data: {
"query": myQuery,
"output": "json"
},
success: myCallBack2,
error: myError
});
console.log('After .ajax');
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="//raw.github.com/botmonster/jquery-bootpag/master/lib/jquery.bootpag.min.js"></script>
<div id="page-selection1" "></div>
<div id="result " class="result "></div>
<div id="page-selection2 "></div>
<script>
$('#page-selection1,#page-selection2').bootpag({
total: 50,
page: 1,
maxVisible: 5,
leaps: true,
firstLastUse: true,
first: 'First',
last: 'Last',
wrapClass: 'pagination',
activeClass: 'active',
disabledClass: 'disabled',
nextClass: 'next',
prevClass: 'prev',
lastClass: 'last',
firstClass: 'first'
}).on("page ", function(event, num) {
$("#result ").html("Page " + num);
});
</script>
I am expecting to show part of the results instead Page 1, Page 2... in #result according to a limit per page.
I have a javascript code which renders <ol><li></li></ol> , Using a json from the server . The code looks something like this
function loadWorkFlowRules() {
var wf_id = <?php echo $wf->id; ?>;
$.post("/api/wfengine/get_wf_rules/", {
wf_id: wf_id
}, function(result) {
var wf_rules = JSON.parse(result).data;
if (makeView(wf_rules)) {
toastr.success('The Rules are Successfully Loaded!');
} else
toastr.info('Welcome to Work Flow Editor');
});
}
function makeView(wf_rules) {
//console.log(wf_rules);
var html_str = '',
response = false;
$.each(wf_rules, function(key, value) {
if (value.length > 0) {
$.each(value, function(key1, value1) {
var ui_l1 = '<li class="alert mar" data-id="' + value1.id + '" data-name="' + value1.name + '" style=""><div class="dd-handle state-main">' + value1.name + '<span class="cust-close" data-dismiss="alert" aria-label="Close"><i class="fa fa-times"></i></span></div><ol>';
html_str = html_str + ui_l1;
if (value1.children.length > 0) {
$.each(value1.children, function(key2, value2) {
$.each(value2, function(key3, value3) {
var ui_l2 = '<li class="alert mar" data-id="' + value3.id + '" data-name="' + value3.name + '" style=""><div class="dd-handle state-main">' + value1.name + '<span class="cust-close" data-dismiss="alert" aria-label="Close"><i class="fa fa-times"></i></span></div><ol>';
html_str = html_str + ui_l2;
if (value3.children.length > 0) {
$.each(value3.children, function(key4, value4) {
if (value4.length > 0) {
var ui_l3 = '<li class="dd-item alert mar action" data-id="' + value4[0].id + '" data-name="' + value4[0].name + '" data-api="' + value4[0].api + '" data-url="' + value4[0].url + '" data-json="' + value4[0].json + '" style=""><div class="dd-handle">' + value4[0].name + '<span class="cust-close" data-dismiss="alert" aria-label="Close"><i class="fa fa-times"></i></span> <span class="edit cust-close" data-toggle="modal" data-target="#editAction" ><i class="fa fa-pencil"></i></span></div></li>';
html_str = html_str + ui_l3;
}
})
}
html_str = html_str + '</ol></li>';
});
})
}
html_str = html_str + '</ol></li>';
});
$('.contract_main').html(html_str);
response = true;
} else
response = false;
});
return response;
}
HTML
<div class="dd">
<ol class="dd-list simple_with_drop vertical contract_main">
</ol>
</div>
I got into a situation where Ill have to Bind the data element of the child <li> with an HTML MODAL popup , So that if the value in Modal is updated it shoud change in the Object/Dom also .
I was recommended to use VueJs.
I have went through! the basics of the VueJs , But that didn't cover how I ccan bind complete list from a Json ,
Any help in how I can do this would be great
Currently I don't see any structure of Vue.Js in your code and you are manipulating the JSON data and constructing the HTML in the JS code itself. You can do it in vue way, where you will create an Vue instance, do loading of data in Vue methods and use Vue syntax to iterate over data and other things. One Simple example you can see in this fiddle or in below code:
new Vue({
el: '#app',
data: {
jsonData: []
},
mounted () {
this.loadJsonData();
},
methods: {
loadJsonData(){
setTimeout(()=>{
this.jsonData = ["first", "Second", "Third", "And So On"]
}, 300)
}
}
})
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<ul>
<li v-for="data in jsonData">{{data}}</li>
</ul>
</div>
You can look at vue-hackernews to understand more about structuring of code, How to fetch data from remote APIs in JSON format and display it.
I am trying to figure out how to avoid looping in JavaScript.
I have this code:
$.ajax({
url : '<?php echo base_url()?>project/search_project_structure_stage',
type: 'POST',
data: {
project_id: $('#project_id').val()
},
success : function(stages)
{
var stages = $.parseJSON(stages);
for (var i = 0; i < stages.length; i++)
{
stageID = stages[i].ID;
stagename = stages[i].StageName;
stageorder = stages[i].ordStage;
stagetypecode = stages[i].StageCode;
projectid = stages[i].PID
var html_stage = "<div class='row col-sm-10'><ol id='"+stageID+"' class='group_stage'>" +
"<li style='list-style:none' class='container span1'>" +
"<a class='expand_batch'><i class='fa fa-folder'></i> " + stagename +
" [" + stagetypecode +
"] (" + stageorder +
")</a>" +
"<a class='icon_edit_stage' id='"+stageID+"'>" +
"<i class='fa fa-pencil fa-fw icon'></i>" +
"</a>" +
"<a class='scopy' sid='"+stageID+"' pid='"+projectid+"'>" +
"<i class='fa fa-copy fa-fw icon'></i>" +
"</a>";
$('#stage').append(html_stage);
$.ajax({
url : '<?php echo base_url()?>project/search_project_structure_batch',
type: 'POST',
data: {
'stage_id': stageID,
},
success : function(batch)
{
var batch = $.parseJSON(batch);
for (var i = 0; i < batch.length; i++)
{
batchID = batch[i].BatchID;
batchname = batch[i].BatchName;
batchorder= batch[i].ordBatch;
stageid = batch[i].StageID;
projectid = batch[i].Project_ID;
var html_batch = "<ol id='"+batchID+"' class='group_batch batch'>" +
"<li style='list-style:none' class='container span2'>" +
"<a class='expand_activity'>" +
"<i class='fa fa-list'></i> " + batchname +
" (" + batchorder +
")</a>" +
"<a class='icon_edit_batch' id='"+batchID+"'>" +
"<i class='fa fa-edit fa-fw icon'></i>" +
"</a>" +
"<a class='bcopy' bid='"+batchID+"' sid='"+stageid+"' pid='"+projectid+"' data-toggle='modal'>" +
"<i class='fa fa-copy fa-fw icon'></i>" +
"</a>";
$('#'+stageid).append(html_batch);
}
$( ".bcopy" ).click(function()
{
batch_id = $(this).attr('bid');
stage_id = $(this).attr('sid');
batch_project_id = $(this).attr('pid');
$('#batch_id').val(batch_id);
$('#batch_stage_id').val(stage_id);
$('#batch_project_id').val(batch_project_id);
$('#myModalCloneBatch').modal('show');
$( "#clone_batch" ).click(function()
{
$.ajax({
url : '<?php echo base_url('project/clone_batch')?>',
type: 'POST',
data:
{
batch_id : $('#batch_id').val(),
batch_stage_id : $('#batch_stage_id').val(),
batch_project_id : $('#batch_project_id').val(),
batch_name : $('#batch_name').val(),
batch_quantity : $('#batch_quantity').val()
},
success: function(msg)
{
}
});
});
});
}
});
}
$( ".scopy" ).click(function()
{
stage_id = $(this).attr('sid');
stage_project_id = $(this).attr('pid');
$('#stage_id').append(stage_id);
$('#stage_project_id').append(stage_project_id);
$('#myModalCloneStage').modal('show');
$( "#clone_stage" ).click(function()
{
$('#myModalCloneStage').modal('hide');
document.getElementById('toggle-div').style.display='block';
var target = document.getElementById('wrapper');
var spinner = new Spinner(opts).spin(target);
$.ajax({
url : '<?php echo base_url('project/clone_stage')?>',
type: 'POST',
data:
{
stage_id : $('#stage_id').text(),
stage_project_id : $('#stage_project_id').text(),
stage_name : $('#stage_name').val(),
stage_code : $('#stage_code').val()
},
success: function(msg)
{
document.getElementById('toggle-div').style.display='none';
spinner.stop();
var msg = $.parseJSON(msg);
jo_number = $('#jo_number').val();
$('#cloned_jo_number').append(jo_number);
$('#myModalCloneStageSuccess').modal('show');
}
});
});
});
}
});
As you will notice the $( ".bcopy" ).click(function() is inside the for loop. I just want to ask how to avoid that once I click the <a> tag with class bcopy. It will not follow the for loop?
It happens that when I click the <a> tag it loop.
Put it out side the loop as it is rendering the click event script multiple time and as element is added after DOM loaded you need to use delegated event to make it work:
$("#stage").on('click','.bcopy',function()
{
// your code goes here
});
you can read more in detail from here
Your question is not very clear, but if you want things to happen in order, you should try using the Deferred Object in jQuery.
If you want the handler for the click to only be assigned after your for loop, add a function that runs the for loop first and another that assigns the handler second, to a deferred object, before calling deferred.resolve(). There is also a lot of potential to help clean your code using the Deferred Object.