Perform an async task with a web worker JavaScript - javascript

I want to show a loading icon while a task is being performed and then hide the icon after it has been performed. I need to use a web worker for the loading icon to show. The admin at This forum post said to use a web worker.
This is the code to execute in the web worker:
function getTheClients(xml) {
console.log(xml);
var client = xml.getElementsByTagName("WebClientList");
if(client.length === 0) {
$("#noClients" + platform).empty();
$("#noClients" + platform).append('<p style="margin-top:40px;margin-bottom:20px;text-align:center;">No clients at ' +
getSelectedDropDownOptionName("allVillagesDropDown") + ', ' +
getSelectedDropDownOptionName("allLocationsDropDown") + '.</p>');
$("#noClients" + platform).attr("style", "display: block");
$("#theClientsList" + platform).attr("style", "display: none");
} else {
$("#noClients" + platform).attr("style", "display: none");
$("#theClientsList" + platform).attr("style", "display: block");
}
for (i=0; i < client.length; i++) {
var firstName = client[i].getElementsByTagName("givenName")[0].childNodes[0];
var lastName = client[i].getElementsByTagName("familyName")[0].childNodes[0];
var oid = client[i].getElementsByTagName("oid")[0].childNodes[0];
var nhi = client[i].getElementsByTagName("nhi")[0].childNodes[0];
var dwelling = client[i].getElementsByTagName("dwelling")[0].childNodes[0];
var photo = client[i].getElementsByTagName("photo")[0].childNodes[0];
if (!photo) {
photo = "";
} else {
photo = photo.nodeValue;
}
firstName = firstName ? firstName.nodeValue : "";
lastName = lastName ? lastName.nodeValue : "";
oid = oid ? oid.nodeValue : "";
nhi = nhi ? nhi.nodeValue : "";
dwelling = dwelling ? dwelling.nodeValue : "";
var letterDwelling = dwelling ? dwelling[0].toUpperCase() : "";
var letterLastName = lastName ? lastName[0].toUpperCase() : "";
console.log(photo);
dataSource.add({photo: photo, firstName: firstName,lastName: lastName,oid: oid,nhi: nhi,dwelling: dwelling, letterDwelling: letterDwelling, letterLastName: letterLastName});
}
if (clientListViewHasNotLoaded) {
searchFilter = "lastName";
listGroup = "letterLastName"
console.log("e");
$("#theClientsList" + platform).append('<ul id="flat-listview' + platform + '" class="listView' + platform + '" style="width: 100%; margin-bottom:10px; margin-top:10px;"></ul>');
initListView({
field: "lastName",
operator: "startswith",
placeholder: "Search by last name"
}
);
$("#flat-listview" + platform).data("kendoMobileListView").setDataSource(dataSource);
clientListViewHasNotLoaded = false;
}
}
here is the code I'm using to create a web worker, before I take the next step and incorporate my above function:
the script (webServiceScript.js):
self.onmessage = function(event) {
var results = event.data;
// do something
// Done:
postMessage(results);
};
The calling code:
var worker = new Worker('scripts/webServiceScript.js');
worker.onmessage = function(event) {
// Do something with event.data, then hide the spinner.
app.showLoading();
};
app.hideLoading();
worker.postMessage({args: ' foo bar '});
I would like to incorporate my function at the top of the question into the script file (to be used in a web worker). When I incorporate my above function into the script, I need to pass my variable called xml.
Any help greatly appreciated, I'm struggling to understand the documentation here.

As we were discussing in comments, all you need to do is give the browser a chance to do a repaint. You can accomplish that with setTimeout() like this:
app.showLoading()
setTimeout(function() {
getTheClients(xml);
app.hideLoading();
}, 1);
You can't do setTimeout(getTheClients(xml), 1); because that calls getClients() right away and then passes the return result from that to setTimeout(). Instead, you have to pass just a function reference to setTimeout() as shown above.

Related

Email is not sending

Code Runs No Errors But I Do Not Receive and email when I check my gmail
This line is the issue I believe I am writing this incorrectly so its not sending the email help please
if(values.getDisplayValues() === "On-going" || values.getDisplayValues() === "" && values1.getDisplayValues() >= 80)
Rest of the code:
function sendEmail(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var SpreadsheetID = ss.getSheetId();
var spreadsheetURL = ss.getUrl();
var SpreadsheetID = spreadsheetURL.split("/")[5];
var filterViewName = 'PO_Log Precentage';
var filterViewID = filterId(SpreadsheetID, filterViewName);
var url = createURL(spreadsheetURL, filterViewID);
Logger.log(url);// Testing to see the correct url is created
var po_numID = ss.getSheetByName("Purchase Orders List").getRange("A2").getDisplayValue().substr(0,3);
Logger.log(po_numID);
var email_va = ss.getSheetByName("Purchase Orders List");
var values = email_va.getRange("Q2:Q");
var values1 = email_va.getRange("T2:T");
Logger.log(values)
var emailDataSheet = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/17G0QohHxjuAcZzwRtQ6AUW3aMTEvLnmTPs_USGcwvDA/edit#gid=1242890521").getSheetByName("TestA");
Logger.log(emailDataSheet.getSheetName());
var emailData = emailDataSheet.getRange("A2:A").getDisplayValues().flat().map(po => po.substr(0,3));
Logger.log(emailData)
var subject = po_numID + " Po Log Daily Notification ";
var options = {}
options.htmlBody = "Hi All, " + "The following" + '<a href=\"' +url+ '" > Purchase Orders </a>' + "are over 80% spent" + "";
// I believe this if statement is the problem I am writing it in correctly
if(values.getDisplayValues() === "On-going" || values.getDisplayValues() === "" && values1.getDisplayValues() >= "80%"){
emailData.every((po, index) => {
if (po == po_numID){
const email = emailDataSheet.getRange(index + 2,7).getValue();
console.log(email);
MailApp.sendEmail(email, subject, '', options);
return false;
} else {
return true;
}
});
}
}
https://docs.google.com/spreadsheets/d/1QW5PIGzy_NSh4MT3j_7PggxXq4XcW4dCKr4wKqIAp0E/edit#gid=611584429
Here is the spread sheet
values.getDisplayValues() gives you an array.
Basically it makes no sense to compare an array and a string with === and >= etc.
You need to decide which element of the array there should be. May be something like values.getDisplayValues()[0][0] (because it's likely an 2D-array). I can't check your code, so just a guess.

nodeJS Crawler : unable to get the tagname associated with search word

I have created a crawler in NodeJS
I have a website : "http://www.google.com" for which I have written the crawler
Technology used is nodeJS, cheerio
Sample example of what I have achieved :
For example , lets search google.com. there is a button called "google search".
Let us search for the text "google search". Today my crawler can find the word in the page and say it has found it.
Today it shows : text " google search" found on google.com
What I need the result to be :
What it needs to do is in addition to finding text, also tell me the tag name , that in this case is a button
Needed output is : text "google search" found on google.com of "TAGNAME: BUTTON"
I tried using indexOf, but it isn't working. Please suggest how to do ?
Here is the code
!!!
index.js
var request = require('request');
var cheerio = require('cheerio');
var URL = require('url-parse');
var START_URL = "https://www.mytravelexp.com/";
var SEARCH_WORD ="Pack your travel essentials";
var MAX_PAGES_TO_VISIT = 20;
var pagesVisited = {};
var numPagesVisited = 0;
var pagesToVisit = [];
var url = new URL(START_URL);
var baseUrl = url.protocol + "//" + url.hostname;
pagesToVisit.push(START_URL);
crawl();
function crawl() {
if(numPagesVisited >= MAX_PAGES_TO_VISIT) {
console.log("Reached max limit of number of pages to visit.");
return;
}
var nextPage = pagesToVisit.pop();
if (nextPage in pagesVisited) {
// We've already visited this page, so repeat the crawl
crawl();
} else {
// New page we haven't visited
visitPage(nextPage, crawl);
}
}
function visitPage(url, callback) {
// Add page to our set
pagesVisited[url] = true;
numPagesVisited++;
// Make the request
request(url, function(error, response, body) {
console.log("***************************")
console.log(" Visiting page: " + url + '\n');
if(response.statusCode !== 200) {
callback();
return;
}
// Parse the document body
var $ = cheerio.load(body);
var isWordFound = searchForWord($, SEARCH_WORD);
if(isWordFound) {
console.log(' ' + SEARCH_WORD + ' found at page ' + url);
collectInternalLinks($);
callback();
} else {
collectInternalLinks($);
// In this short program, our callback is just calling crawl()
callback();
}
});
}
function searchForWord($, word) {
var bodyText = $('html > body').html().toLowerCase();
return(bodyText.includes(word.toLowerCase()) !== -1);
}
function collectInternalLinks($) {
var relativeLinks = $("a[href^='/']");
relativeLinks.each(function() {
pagesToVisit.push(baseUrl + $(this).attr('href'));
});
var absoluteLinks = $("a[href^='http']");
absoluteLinks.each(function() {
pagesToVisit.push($(this).attr('href'));
});
}
if ( $('123')[0].name === 'button' ){
console.log($('button').contents().first().text());
console.log( $('123').attr('name') );
}

Looping round array and concatenating results Javascript

Please see my code below, I am interrogating active directory and retrieving back two fields, "name" and "cn". I want to concatenate these in an array and then assign to my drop down list. i.e. name + ' ' + cn. The code below publishes my results wrongly and is displaying all names and cn as individual results i.e. not concatenated.
Can someone advise me and put me in the right direction?
thanks,
George
try
{
// Get LDAP Context
ctx = LdapServices.getLdapContext();
//Specify the search scope
ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
var searchFilter = "(&(objectClass=group))";
//Specify the Base for the search
var searchBase = "ou=Licensed Applications,ou=SCCM Apps,ou=Applications,ou=Groups,dc=XXX,dc=XX,dc=XX";
//initialize counter to total the group members
var totalResults = 0;
//Specify the attributes to return
var returnedAtts=["name", "cn"];
ctls.setReturningAttributes(returnedAtts);
//Search for objects using the filter
var answer = ctx.search(searchBase, searchFilter, ctls);
//Loop through the search results
while (answer.hasMoreElements())
{
var sr = answer.next();
var attrs = sr.getAttributes();
if (attrs != null)
{
try
{
for (var ae = attrs.getAll();ae.hasMore();)
{
var attr = ae.next();
var pos = attr.toString().indexOf(":",0);
var attributeName = attr.toString().substring(0,pos);
var name = "";
var cn = "";
for (var e = attr.getAll();e.hasMore();totalResults++)
{
if(attributeName == "name")
{
name = e.next().replace('SCCM_','');
}
if(attributeName == "cn")
{
cn = e.next();
}
}
listItems.push(name + ' (' + cn + ')');
}
}
catch (e)
{
log("Problem listing items: " + e);
}
}
}
}
catch (e)
{
log("Problem searching directory: " + e);
}
finally
{
// Close LDAP Context
ctx.close();
}
I don't know what javascript library you use to have JNDI like code into, but from the purely LDAP point of view :
An attribute can be multi-valued, so every attributes value are returned in a array, even if single valued (possible exception for the dn), for example :
{
"dn":"cn=user,dc=example,dc=com",
"name":["username"],
"cn":["commonname"]
}
If your library works like JNDI, a way to do it could be :
After the line : var attrs = sr.getAttributes();
if (attrs != null) {
try {
log ("name: " + attrs.get("name").get());
log ("cn: " + attrs.get("cn").get());
} catch (e) {
log ("Problem listing attributes from Global Catalog: " + e);
}
}

class inheritance in javascript/angular

I am working on my hello world project. I have two pages let's call them "configuration" and "add configuration" *.html. Each one has its own controller like this:
angular.module('MissionControlApp').controller('ConfigController', ConfigController);
angular.module('MissionControlApp').controller('AddConfigController', AddConfigController);
Now, each controller has some properties that very much overlap:
function ConfigController($routeParams, ConfigFactory, $window){
var vm = this;
vm.status;
vm.projectId = $routeParams.projectId;
vm.selectedProject;
vm.configurations;
vm.selectedConfig;
vm.selectedRecords;
vm.filteredConfig;
vm.newFile;
vm.fileWarningMsg = '';
vm.addFile = function(){
var filePath = vm.newFile;
var encodedUri = encodeURIComponent(filePath);
vm.fileWarningMsg='';
ConfigFactory
.getByEncodedUri(encodedUri).then(function(response){
var configFound = response.data;
var configNames = '';
var configMatched = false;
if(response.status === 200 && configFound.length > 0){
//find an exact match from text search result
for(var i = 0; i < configFound.length; i++) {
var config = configFound[i];
for(var j=0; j<config.files.length; j++){
var file = config.files[j];
if(file.centralPath.toLowerCase() === filePath.toLowerCase()){
configMatched = true;
configNames += ' [' + config.name + '] ';
break;
}
}
}
}
if(configMatched){
vm.fileWarningMsg = 'Warning! File already exists in other configurations.\n' + configNames;
} else if(filePath.length > 0 && filePath.includes('.rvt')){
var file1 = { centralPath: filePath };
vm.selectedConfig.files.push(file1);
vm.newFile = '';
} else{
vm.fileWarningMsg = 'Warning! Please enter a valid file.';
}
}, function(error){
vm.status = 'Unable to get configuration data: ' + error.message;
});
};
My AddConfigController also wants to have the same functionality for addFile() so I just copy pasted the same code, but coming from C# i am sure i can do some class inheritance here, and just inherit from ConfigController and extend...right?
If this is super noob question. then apologies. js is a bit of a mystery to me.
function AddConfigController($routeParams, ConfigFactory, $window){
var vm = this;
vm.status;
vm.projectId = $routeParams.projectId;
vm.selectedProject = {};
vm.newConfig = {};
vm.newFile;
vm.fileWarningMsg = '';
vm.addFile = function(){
var filePath = vm.newFile;
var encodedUri = encodeURIComponent(filePath);
vm.fileWarningMsg='';
ConfigFactory
.getByEncodedUri(encodedUri).then(function(response){
var configFound = response.data;
var configNames = '';
var configMatched = false;
if(response.status === 200 && configFound.length > 0){
//find an exact match from text search result
for(var i = 0; i < configFound.length; i++) {
var config = configFound[i];
for(var j=0; j<config.files.length; j++){
var file = config.files[j];
if(file.centralPath.toLowerCase() === filePath.toLowerCase()){
configMatched = true;
configNames += ' [' + config.name + '] ';
break;
}
}
}
}
if(configMatched){
vm.fileWarningMsg = 'Warning! File already exists in other configurations.\n' + configNames;
} else if(filePath.length > 0 && filePath.includes('.rvt')){
var file1 = { centralPath: filePath };
vm.selectedConfig.files.push(file1);
vm.newFile = '';
} else{
vm.fileWarningMsg = 'Warning! Please enter a valid file.';
}
}, function(error){
vm.status = 'Unable to get configuration data: ' + error.message;
});
};
Since you asked about inheritance and you appear to be using ECMAScript 5, let me suggest taking a look at Object.create(). Specifically, the classical inheritance example.
That said, in AngularJS, a better solution would be to create a Service that manages files or configurations and put the addFile function in there. That way, both controllers could inject the service and call the same function when it is time to add a file. Likewise, other services and controllers that may need access to this functionality could inject it as well.

Owner dropdown not filtering Story cardboard

I built a custom cardboard mashup to display all user stories that are in a "committed" iteration and beloning to the current project, or any child project. This much works well. I then added an Owner dropdown box (limited to Team Members only), to filter the stories on the cardboard. The resulting query value appears to be well formatted, yet no stories are displayed. I used an alert to copy the query string and paste it into a custom grid, which returned the expected list of stories.
Below is my code. Any assistance is appreciated.
var rallyDataSource;
var cardboard;
var ownerDropdown;
function refreshCardboard() {
var cardboardConfig = {
types: ["Defect", "HierarchicalRequirement"],
attribute: "ScheduleState",
fetch: "Name,FormattedID,Owner,ObjectID"
};
var query = rally.sdk.util.Query.and(['Iteration.Name != ""', 'Iteration.State = "Committed"']);
if (ownerDropdown) {
var ownerQuery = ownerDropdown.getValue();
if (ownerQuery != 'ALL') {
query = '(' + query + ' AND Owner.Name = "' + ownerQuery + '")';
}
}
cardboardConfig.query = query;
if (!cardboard) {
cardboard = new rally.sdk.ui.CardBoard(cardboardConfig, rallyDataSource);
cardboard.display("cardboardDiv");
} else {
cardboard.refresh(cardboardConfig);
}
}
function buildOwnerDropdown() {
var teamMembersQuery = {
key: "teamMembers",
type: "User",
fetch: "UserName,DisplayName",
query: '(TeamMemberships = /project/__PROJECT_OID__)'
};
rallyDataSource.findAll(teamMembersQuery, function (results) {
var ownerItems = [{ label: "-- ALL --", value: "ALL"}];
rally.forEach(results.teamMembers, function (teamMember) {
ownerItems.push({ label: teamMember.DisplayName, value: teamMember.UserName });
});
ownerItems.sort();
var ownerDropdownConfig = {
showLabel: true,
label: "Owner:",
items: ownerItems
};
ownerDropdown = new rally.sdk.ui.basic.Dropdown(ownerDropdownConfig);
ownerDropdown.display("ownerDropdownDiv");
});
}
function onLoad() {
rallyDataSource = new rally.sdk.data.RallyDataSource(
'__WORKSPACE_OID__',
'__PROJECT_OID__',
'__PROJECT_SCOPING_UP__',
'__PROJECT_SCOPING_DOWN__');
buildOwnerDropdown();
refreshCardboard();
}
rally.addOnLoad(onLoad);
</script>
</head>
<body>
<div id="ownerDropdownDiv"></div>
<input id="refreshButton" type="button" value="Filter" onclick="refreshCardboard()"/>
<div id="cardboardDiv"></div>
</body>
You're really close to the mark - the problem lies here:
var query = rally.sdk.util.Query.and(['Iteration.Name != ""', 'Iteration.State = "Committed"']);
if (ownerDropdown) {
var ownerQuery = ownerDropdown.getValue();
if (ownerQuery != 'ALL') {
query = '(' + query + ' AND Owner.Name = "' + ownerQuery + '")';
}
}
Rally's query syntax requires another nested set of parentheses when adding another AND condition. So when you concatenate on your third condition, you are ending up with a query clause that looks like this:
((Iteration.Name != "") AND (Iteration.State = "Committed")) AND (Owner.Name = "user#company.com")
When it needs to look like this:
(((Iteration.Name != "") AND (Iteration.State = "Committed")) AND (Owner.Name = "user#company.com"))
I slightly modified your refreshCardboard() function's query logic as follows, and your code seems to work now for me.
....
var queryArray = new Array('Iteration.Name != ""', 'Iteration.State = "Committed"');
var query;
var selectedOwner = ownerDropdown.getValue();
if (ownerDropdown) {
if (selectedOwner != 'ALL') {
var ownerClause = 'Owner.Name = "' + selectedOwner + '"';
queryArray.push(ownerClause);
}
}
query = rally.sdk.util.Query.and(queryArray);
cardboardConfig.query = query;
....

Categories

Resources