I'm working on a .NET Core project for my company where work orders are loaded from our SQL database using Entity Framework, filtered and then displayed as markers on a map through Google Maps API for our installers.
We have two types of filters: one that gets included in an Ajax POST, and one that filters locally to decrease load times and performance issues. What I'm trying to do is load the local filter items (lists that are included in the response when calling the initial Ajax POST). If the list of filter items exceeds 5 items, I want them to collapse to only 5 items and insert an anchor which expands (utilizes jQuery's toggle()) showing the rest of the items in that list.
This is the excerpt from the JavaScript function which takes care of that:
filterItems
.forEach((filterItem, i) => {
var localItem = '<label class="' + selectorContainerClass
+ ' selectorContainer" id="' + selectorContainerIdPrefix + filterItem.key
+ '"><input id="' + convertValToEng(filterItem.value)
+ '" type = "checkbox" class="filled-in navy" name="' + inputName
+ '" value="' + filterItem.key
+ '" onchange="localFilter(this, this.value)" /><span class="selector-value">'
+ filterItem.value
+ '</span> <span id="' + paramName + 'Cnt__' + filterItem.key
+ '" class="selector-count"></span></label ><br />';
document.querySelector("#" + colId).insertAdjacentHTML('beforeend', localItem);
if (i >= 5) {
$("#" + colId + " #" + selectorContainerIdPrefix + filterItem.key).addClass("collapse");
$("#" + colId + " #" + selectorContainerIdPrefix + filterItem.key).toggle(100);
$("#" + colId + " #" + selectorContainerIdPrefix + filterItem.key + " + br").toggle(100);
}
});
if (filterItems.length > 5) {
//TODO: Fix the bug here; the .filter-collapse element is not being inserted under local installers.
var newEl = '<a class="filter-collapse" onclick="toggleFilterExpand(false, this)";><i class="material-icons">expand_more</i></a>';
document.getElementById(colId).insertAdjacentHTML('beforeend', newEl);
}
I should be getting a newEl inserted under the "Installer" column (8 installers, 3 of them not being displayed), but I'm not. I've tried jQuery's after() and insertAfter() methods, but neither of those worked. newEl is being generated for the "Area" column, as it should, but for the "Installer" column it's not.
I've also tried inserting the element manually through the console window with the exact same code and it works.
Would appreciate some help with this as I feel lost regarding this issue.
Thanks.
It turned out to be a stupid mistake on my end where I was removing the element newEl from the all the other filter lists before inserting a new one to the currently iterated one.
I'm attempting to split a string I'm passing into
$("#groupUL").append("<li>" + "<h2>About Item:</h2> " + response.data[i].message + "<br /> " + "<h2>Posted By:</h2> <a href='#' onclick='splitName('" + response.data[i].from.name + "');'>" + response.data[i].from.name + "</a>" + "<br />");
Seems to be passing me the error
SyntaxError: syntax error
splitName(
Not sure how that's wrong...Here is the splitname function if that helps
function splitName(txt){
var myString = txt;
var mySplitResult = myString.split(" ");
console.log("The first element is " + mySplitResult[0]);
console.log("<br /> The second element is " + mySplitResult[1]);
console.log("<br /> The third element is " + mySplitResult[2]);
};
It's too hard to get it right when you put quotes in quotes in quotes and you try to escape it right. You got it wrong.
A solution is to make it in small parts :
var action = "splitName('" + response.data[i].from.name + "');";
$("#groupUL").append("<li>" + "<h2>About ... onclick=\""+action+"\">...");
But the best solution would be to follow best practice, that is not inline the javascript but use jQuery's binding function :
$("#groupUL").append("... <a id=myid ...");
$("#myid").click(function(){ splitName(response.data[i].from.name) });
I think the only problem with your code is with your readability issue. So I would suggest please improve it. Lets have a look at it. My code example # JSbin.
Here is the code :- (which i think is better)
var response = {
data : {
message: 'Cleaning code',
from: {
name: 'Clean Code works'
}
}
};
var li = $('<li>'); //Create empty li (Not Appending to DOM now due to performance issues)
$('<h2>').html('About Item:' + response.data.message + '<br />').appendTo(li);
$('<h2>').html('Posted By:').appendTo(li);
$('<a>').attr('href', '#')
.html(response.data.from.name)
.appendTo(li)
.click(function() {
splitName(response.data.from.name);
});
$('<br>').appendTo(li);
// Append li to ul (Final operation to DOM)
li.appendTo('#groupUL');
function splitName(txt){
var myString = txt;
var mySplitResult = myString.split(" ");
console.log("The first element is " + mySplitResult[0]);
console.log("The second element is " + mySplitResult[1]);
console.log("The third element is " + mySplitResult[2]);
}
I'm creating a workflow process that will email a body of a form to users in that workflow. I can iterate through the users and send an email but I do not now how to pass the "e" parameters for the body of the email. I actually already have a function that will send the body , but I need to include this in my step process (I think).
Hear is my code that will send email
function sendEmail_(e) {
var sheet = SpreadsheetApp.openById("0AuCblud0Ss7sdfA1bXZjYXA0Y0IhthkhUQm5vWG02MVE").getActiveSheet();
var row = sheet.getLastRow()+1;
sheet.getRange(row,3).setValue(row);
var range = sheet.getRange(sheet.getLastRow(),1,1,23);
range.setValues([[e.parameter.LastName,e.parameter.FirstName,row /*e.parameter.DivisionName*/,e.parameter.EffectiveDate,e.parameter.Status,
e.parameter.Network,e.parameter.EmployeeNewPosition,e.parameter.DivisionFolder,e.parameter.SpecificIndividual,
e.parameter.Email,e.parameter.username,e.parameter.who,e.parameter.Banner,e.parameter.RMS ,e.parameter.HAPPY,e.parameter.Sweeps,
e.parameter.Comcate,e.parameter.Netviewer,e.parameter.NetDispatcher,e.parameter.IMARS,"pending", e.parameter.DivHeadEmail, e.parameter.Director]]);
var body = '<form action= <form action = " https://sites.google.com/a/macros/wichitafallstx.gov/s/AKfycbxAOGO6q9ofauf34xlDA9sLG8sUXeZsuvQkDKATOQ/exec" method ="post">' +
"<b>Last Name:</b>" + e.parameter.LastName + '<br><br>' +
"<b>First Name:</b>" + e.parameter.FirstName + '<br><br>' +
"<b>Division Name:</b>" + e.parameter.DivisionName + '<br><br>' +
"<b>Effective Date:</b>" + e.parameter.EffectiveDate + '<br><br>' +
"<b>Employee Status:</b>" + e.parameter.Status + '<br><br>' +
"<b>Network:</b>" + e.parameter.Network + '<br><br>' +
"<b>Employee New Position:</b>" + e.parameter.EmployeeNewPosition + '<br><br>' +
"<b>Division Folder:</b>" + e.parameter.DivisionFolder + '<br><br>' +
"<b>Specific Individual:</b>" + e.parameter.SpecificIndividual + '<br><br>' +
"<b>Email:</b>" + e.parameter.Email + '<br><br>' +
"<b>Username:</b>" + e.parameter.username + '<br><br>' +
"<b>who:</b>" + e.parameter.who + '<br><br>' +
"<b>Banner:</b>" + e.parameter.Banner + '<br><br>' +
"<b>RMS:</b>" + e.parameter.RMS + '<br><br>' +
"<b>HAPPY:</b>" + e.parameter.HAPPY + '<br><br>' +
"<b>Sweeps:</b>" + e.parameter.Sweeps + '<br><br>' +
"<b>Comcate:</b>" + e.parameter.Comcate + '<br><br>' +
"<b>Netviewer:</b>" + e.parameter.Netviewer + '<br><br>' +
"<b>NetDispatcher:</b>" + e.parameter.NetDispatcher + '<br><br>' +
"<b>IMARS:</b>" + e.parameter.IMARS +
'<br />' +
'<br />' +
'<input type="hidden" name="row" value=" ' + row +' "/>' +
'<input type="submit" value="Approve" onclick="approve()" />' +
'</form>'
;
// var owners = e.parameter.DivHeadEmail;
// var mail = MailApp.sendEmail(owners, "test",'' , {htmlBody:body});
}
I need to email the html body from the code above with the step in the work flow in this "createStep" function. I dont know how to reference the variable "body" from the code above to this function or even if I could include the html body in this function. How would I do this?
function createStep(approvers) {
var step = new Object();//javascript object
step['numberOfApprovers'] = approvers.length; //set number of approvers passed in array
step['approvers'] = approvers.slice(0); //slice copies array
step['status'] = 'pending'; //set statust to pedning
for (var i in approvers)
step[approvers[i]] = 'pending'; //iterate field that indicates specific status
for (var m in approvers)
step[approvers[m]] = MailApp.sendEmail(approvers, "test", "test",{htmlBody:body});
return step
}
If you want to include the body variable in both functions, declare the variable outside the functions:
var body;
function sendEmail_(e) {
...
body = ...
}
function createStep(approvers) {
...
sendEmail(..., {htmlBody:body}
..
}
However, I don't think you can send POST parameters to a script, GET should work. But I haven't tried it myself.
On second thought, and trying to understand the process, why not create a web app that just displays the info on the screen, with an Approve button under it, and send a link to that app to each approver?
Advantage is that you can give access to the script to logged in users only, and check that the right person is approving--makes it more safe.
Note that you can use the ObjDB library to easily retrieve a row from a spreadsheet:
http://www.harryonline.net/scripts/objdb-storing-data-with-google-apps-script/482
I would create a spreadsheet with two worksheets. The first contains the data, the second contains the list of approvers. One column in the first sheet indicates the last approver.
So your script checks the rows in the data worksheet, and sends an email containing the data of a row that has not been approved yet. It includes a link to approve. The receiver checks the data, and clicks on the link to approve.
This brings him to a script, where he has to log in. The script checks the user with the expected approver, and if OK, increases the value in the approver column in the data sheet. While there are more approvers, continue the loop.
I'm trying to append information to my page from two different JavaScript arrays. It looks like this.
var i = 0;
var videoArr=["big long array"];
var descriptArr=["big long array"];
function appendVideo(i) {
var url = "http://i.ytimg.com/vi/" + videoArr[i] + "/mqdefault.jpg";
$("#history").append("<img src=\"" + url + "\" width=\"120\" height=\"68\" />**NEED TO PRINT descriptArr[i] HERE**<br />");
}
function loadHistory() {
while (i < '.$length.') {
appendVideo(i);
i = i + 1;
}
}
So the above code is appending all the elements from the videoArr no problem. The problem is the descriptArr is full of free text descriptions that I need to print beside each videoArr element. What's he best way to do this? I presume it's not document.write(descriptArr[i])...
Try this, as long as you are sure that descriptArr does not contain any HTML literals.
$("#history").append("<img src=\"" + url + "\" width=\"120\" height=\"68\" />" + descriptArr[i] + "<br />");
Not the best way, but just try something like this
$("#history").append("<img src=\"" + url + "\" width=\"120\" height=\"68\" />" + descriptArr[i] + "<br />");
Ive used this for achieving the same thing:
aDate = (document.getElementById("datepicker").value);
$('.daysContain').find('div').eq(dateArray.length-1).prepend(aDate + '<br>');
Hey all, i have been trying for a few minutes on this problem and i can not seem to figure out how to correct it. I tend to have the hardest time doing stuff like this when it involves more than one varable within the function.
Here is the code:
var tempString = "thePrompt('Are you sure you wish to delete this?', 'theDel('" + IDnum + "', '" + theTitle + "', \'" + temperDay + "\', \'" + temperMonth + "\', \'" + temperYear + "\', \'" + DDiff + "\')";
html +=
"<div id='theTable" + IDnum + "' class='fc-event fc-event-hori fc-corner-left fc-corner-right' style='position:absolute; margin-top: 15px; z-index:8;left:"+left+"px'><div id='apDEL' style='position:relative;width:0px;height:0px;z-index:1000; top:-13px; left:2px; float:left;'><img src='img/xCal.png' width='15' height='15' alt='' border='0' onclick=\"" + tempString + "\" /></div>" + (ETC ETC...)
The error i keep getting is this:
Error: missing ) after argument list
Line: 1, Column: 68
Source Code:
thePrompt('Are you sure you wish to delete this posting?', 'theDel('105', '50 points for visiting us today!!!!', '13', '3', '2010', '2')
And its pointing to the '105'.
As always, any help would be wonderful! :o)
David
EDIT/UPDATE
Ok, so now i have moved some things around and i got it working (that is sending the values to the popup prompt box BUT for some reason it doesn't see my function after i hit the delete button! This is because the prompt is on the main page and the code i am working with is inside a iframe.
function theDel(theID, theTitle, day, month, year, DDiff)
{
var tempString = "delClientE(" + theID + ", '" + theTitle + "', " + day + ", " + month + ", " + year + ", " + DDiff + ")";
parent.thePrompt('Are you sure you wish to delete this event?', tempString);
}
The delete button values now look like this:
delClientE(110, 'sadfsadfsdf', 14, 3, 2010, 2); jQuery.prompt.close();
However, even putting parent.delClientE doesnt find the function either... How can i call it from within the iframe when the prompt box is outside of that?
David
Keeping track of escaping in nested contexts is really hard, and because when you get it wrong you've very often given yourself a script-injection security problem, it's much better to avoid creating HTML/JS by sticking strings together.
Instead, use DOM methods to assign your event handler from JavaScript and say goodbye to all that irritating backslash and quoting stuff:
var img= document.createElement('img');
img.src= 'img/xCal.png';
img.width=img.height= 15;
img.onclick= function() {
if (confirm('Are you sure you wish to delete this?'))
theDel(IDnum, theTitle, temperDay, temperMonth, temperYear, DDiff);
};
div.appendChild(img);
it's because of the quotes here 'theDel('" + you should escape the inner single quotes.
Edit. that is of course, in addition of the missing right paren issue already on the table. :)
I think it's missing at the end of the statement .. your statement looks like this:
var tempString = "thePrompt('question', theDel(params)";
.. where it should have one more closing ')' at the end.
and one more thing you might want to look at is the fact that the arguments in theDel are wrapped in single quotes.
thePrompt('Are you sure you wish to delete this?', 'theDel('105', '50 points for visiting us today!!!!', '13', '3', '2010', '2')' )
And that might be a problem since the params in thePrompt are also wrapped in single quotes so I would make the thePrompt have double quotes arround it's params so it would look something like this:
var tempString = "thePrompt(\"Are you sure you wish to delete this?\", \"theDel(\'" + IDnum + "\', \'" + theTitle + "\', \'" + temperDay + "\', \'" + temperMonth + "\', \'" + temperYear + "\', \'" + DDiff + "\')\")";
David, not sure if this has been answered to your satisfaction yet, but it might be easier to create a temporary variable for this:
var theDel = "theDel('" + IDnum + "', '" + theTitle + "', '" + temperDay + "', '" + temperMonth + "', '" + temperYear + "', '" + DDiff + "')";
var tempString = "thePrompt('Are you sure you wish to delete this?', \' + theDel + \')";
First of all, you'd be far better using event delegation with the js library of your choice.
Failing that, a string interpolation function makes these sorts of things easier:
String.prototype.format = function(values) {
return this.replace(/\{(.+?)\}/g, function(s, key) {
return values[key];
});
}
So long things like this become:
var s = 'blah blah blah "{IDnum}" blah blah blah \'{foosball}\''.format({ IDnum: '1', foosball: 'xyz'});
(If you don't like manipulating String's prototype, you can put the function somewhere else.)
Ok, how about this?
iFrame source
<html>
<head>
<script type="text/javascript">
function localDel(params){
if (window.parent && typeof window.parent.thePrompt==='function')
window.parent.thePrompt('Are you sure you wish to delete this event?', params);
}
</script>
</head>
<body>
<p onclick="localDel([1,'some title', 14, 3, 2010, 2])">delete</p>
<p onclick="localDel([2,'another title', 14, 3, 2010, 2])">delete</p>
</body>
</html>
Parent source
<html>
<head>
<script type="text/javascript">
function thePrompt(msg,params) {
if(confirm(msg)) theDel.apply(this,params);
}
function theDel(id, title, tDay, tMonth, tYear, dDiff) {
alert(id);
// etc...
}
</script>
</head>
<body>
<iframe src="iframe.html" />
</body>
</html>
I finally got it!! YAY! :o)
function theDel(theID, theTitle, day, month, year, DDiff)
{
var tempString = "window.frames.theCal.delClientE(" + theID + ", '" + theTitle + "', " + day + ", " + month + ", " + year + ", " + DDiff + ")";
parent.thePrompt('Are you sure you wish to delete this event?', tempString);
}
I needed the window.frames.theCal in order to call my function. theCal is my iframe id.
David