Add Javascript function return value to output - javascript

I have the following code:
var Faculty180API = {
token: '1a88be52b9e9dd649998c3c1979b6b5c79cc160e',
base_url: 'https://www.faculty180.com/api.php',
account: 'DemoLinks',
last_results: null,
fetch: function(path, params, callback) {
$.ajax((this.base_url + this.make_path(path)), {
data: this.make_params(params),
crossDomain: true,
xhrFields: { withCredentials: true },
success: callback,
dataType: 'json',
error: function(xhr) {
if(xhr.status == 200) {
$('#results').text(xhr.responseText);
}
else {
$('#URL').text(Faculty180API.base_url . HERE);
$('#results').text(xhr.status + ' - ' + xhr.statusText);
}
}
});
},
make_params: function(params){
params['token'] = this.token;
return $.param(params);
},
}
In the line that I have written HERE, I want to add what Function(params) returns to the output. How can I do this?

Haven't tested this, but I'm thinking you can just call it like this:
$('#URL').text(Faculty180API.base_url + Faculty180API.make_params( yourParams ) );
Also note that I changed your . (after base_url) to a +. Dot is string concatenation in PHP; in Javascript it's +

Related

Function is returning value before running inner actions

Using SharePoint's PreSaveAction() that fires when the Save button is clicked, I am trying to run checks and manipulate fields before the form is saved. If PreSaveAction() returns true, the form will be saved and closed.
function PreSaveAction() {
var options = {
"url": "https://example.com/_api/web/lists/getbytitle('TestList')/items",
"method": "GET",
"headers": {
"Accept": "application/json; odata=verbose"
}
}
$.ajax(options).done(function (response) {
var actualHours = response.d.results[0].ActualHours
var personalHours = $("input[title$='Personal Hours']").val();
var regex = /^\d*\.?\d+$/ // Forces digit after decimal point
if (personalHours && regex.test(personalHours)) { // Run if input is not blank and passes RegEx
if (response.d.results[0].__metadata.etag.replace(/"/g, "") == $("td .ms-descriptiontext")[0].innerText.replace("Version: ", "").split('.')[0]) {
// Run if item's data from REST matches version shown in form
addChildItem(id, title, personalHours, actualHours)
}
}
});
return true; // firing before request above begins
}
The function is returning as true before running the jQuery AJAX call which runs addChildItem() that manipulates fields within the form and posts relevant data to a separate list.
function addChildItem(id, title, personalHours, actualHours) {
$.ajax({
method: "POST",
url: "https://example.com/_api/web/lists/getbytitle('ChildList')/items",
data: JSON.stringify({
__metadata: {
'type': 'SP.Data.ChildListListItem'
},
ParentID: id,
Title: title,
HoursWorked: personalHours
}),
contentType: "application/json;odata=verbose",
headers: {
"Accept": "application/json; odata=verbose",
},
success: function (data) {
console.log("success", data);
var actualHoursNum = Number(actualHours);
var personalHoursNum = Number(personalHours);
$("input[title$='Actual Hours']").val(actualHoursNum + personalHoursNum);
$("input[title$='Personal Hours']").val('');
// Input is getting cleared on save but shows previous number when form is opened again
},
error: function (data) {
console.log("error", data);
}
});
}
This is causing the form to accept the field value manipulations but only after the save and before the automatic closure of the form.
I need PreSaveAction() to wait until after addChildItem() is successful to return true but I'm not sure how to do this. I have tried using a global variable named returnedStatus that gets updated when addChildItem() is successful but the return value in PreSaveAction() still gets looked at before the jQuery AJAX call is ran.
How can I solve this?
I got a similar case by setting async: false to add user to group in PreSaveAction.
Original thread
<script language="javascript" type="text/javascript">
function PreSaveAction() {
var check = false;
var controlName = 'MultiUsers';
// Get the people picker object from the page.
var peoplePickerDiv = $("[id$='ClientPeoplePicker'][title='" + controlName + "']");
var peoplePickerEditor = peoplePickerDiv.find("[title='" + controlName + "']");
var peoplePicker = SPClientPeoplePicker.SPClientPeoplePickerDict[peoplePickerDiv[0].id];
if (!peoplePicker.IsEmpty()) {
if (peoplePicker.HasInputError) return false; // if any error
else if (!peoplePicker.HasResolvedUsers()) return false; // if any invalid users
else if (peoplePicker.TotalUserCount > 0) {
// Get information about all users.
var users = peoplePicker.GetAllUserInfo();
for (var i = 0; i < users.length; i++) {
console.log(users[i].Key);
var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/sitegroups(22)/users";
$.ajax({
url: requestUri,
type: "POST",
async: false,
data: JSON.stringify({ '__metadata': { 'type': 'SP.User' }, 'LoginName': '' + users[i].Key + '' }),
headers: {
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val()
},
success: function(data) {
console.log('User Added');
check = true;
},
error: function (error) {
console.log(JSON.stringify(error));
check = false;
}
});
}
}
} else {
console.log('No user');
}
return check;
}
</script>

Prometheus Pushgateway from Browser JS/AJAX

I am searching for an example on how to push metric to the pushgateway via ajax.
echo 'some_metric 42' | curl --user user:pass --data-binary #- https://example.com/metrics/job/author_monitoring/jobname/count_open
with curl it works perfect!
I don't know how to translate this in js/jquery.
Maybe someone has an example
Here is what I got so far.
(function ($, $document) {
"use strict";
function textToBin(text) {
return (
Array
.from(text)
.reduce((acc, char) => acc.concat(char.charCodeAt().toString(2)), [])
.map(bin => '0'.repeat(8 - bin.length) + bin)
.join(' ')
);
}
var username = "user";
var password = "pass";
var metric = 'some_metric 42';
var binaryData = textToBin(metric);
$.ajax({
url: "https://example.com/metrics/job/author_monitoring/jobname/count_open",
data: binaryData,
type: 'POST',
crossDomain: true,
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
},
success: function () {
console.log("Success");
},
error: function () {
console.log('Failed!');
}
});
})($, $(document));
here is the error:
text format parsing error in line 1: invalid metric name
okay I got it.
There is an easy solution, import is the \n at the end of the string.
(function ($, $document) {
"use strict";
var username = "user";
var password = "pass";
var metric = 'some_metric 42\n';
$.ajax({
url: "https://example.com/metrics/job/author_monitoring/jobname/count_open",
data: metric,
type: 'POST',
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Basic " + btoa(username + ":" + password));
xhr.setRequestHeader("Content-Type", "text/plain");
},
success: function () {
console.log("Success");
},
error: function () {
console.log('Failed!');
}
});
})($, $(document));

jQuery Execute function after asynchronous data load

I have created a jQuery function extending its own object $. This function translate those elements attached to the element this:
$.fn.extend({
translate: function(sourceLang, targetLang) {
if($(this).text().trim().length < 1 || !isNaN(parseInt($(this).text().trim())) || sourceLang == targetLang)
return;
let $function = this;
$($function).each(function() {
let $each = this;
$.ajax({
url: 'https://translate.yandex.net/api/v1.5/tr.json/translate',
method: 'GET',
dataType: 'JSONP',
crossDomain: true,
data: {
key: /* my-secret-key */,
text: $($each).text(),
lang: sourceLang + '-' + targetLang
},
success: function(response) {
try {
if(response.code !== 200)
throw "Response: " + response.code;
$($each).text(response.text[0])
} catch(error) {
console.error('Translation error on element: ', $($function).text());
console.error('Message returned by the server:', error);
}
},
error: function(xhr, status, error) {
console.error('Translation error on element: ', $($function).text());
console.error('Message returned by the server:', xhr.responseText);
}
});
});
}
});
After loading the code I do this:
$(document).ready(function() {
let lang = $('html').attr('lang').split('-')[0];
$('td td:visible').translate(lang, "en");
});
Note: the HTML tag looks like this <html lang="es-ES"> depending on the logged user language.
The issue I have is the table loads after a couple of seconds (since we are not in Production environment they could be more than 30). Therefore the previous code block is not useful.
Note: the <tbody> tag is created when the data is added.
What I have tried is:
1. Create a setInterval() and clearInterval() when the $('td:visible').length is greater than 0:
let iv = setInterval(function() {
let lang = $('html').attr('lang').split('-')[0];
let rows = $('tbody td:visible');
if(rows.length > 0) {
rows.translate(lang, "en");
clearInterval(iv);
}
}, 1000);
2. Set a .delay() before the translation:
let isTranslated = false;
while(!isTranslated) {
let lang = $('html').attr('lang').split('-')[0];
let rows = $('tbody td:visible');
if(rows.length > 0) {
rows.delay(1000).translate(lang, "en");
isTranslated = true;
}
}
The memory consumed by the browser is greater than 200MB. I also tried with $('table').on('DOMSubstreeModified', 'tbody', function() {}) but it didn't work.
So, what approach would you recommend to use this translation plugin on this table after it loads its tbody?
Edit 1:
I have changed my code so I perform less API requests, thanks to the recommendation of #lucifer63:
let $function = this;
let collection = [];
let translation = '';
$(this).each(function() {
collection.push($(this).text());
});
let text = collection.join('::');
$.ajax({
url: 'https://translate.yandex.net/api/v1.5/tr.json/translate',
method: 'GET',
dataType: 'JSONP',
crossDomain: true,
data: {
key: /* my-secret-key */,
text: text,
lang: sourceLang + '-' + targetLang
},
success: function(response) {
try {
if(response.code !== 200) {
throw "Response: " + response.code;
}
translation = response.text[0].split('::');
$($function).each(function() {
$(this).text(translation.shift());
});
} catch(error) {
console.error('Message returned by the server:', error);
}
},
error: function(xhr, status, error) {
console.error('Message returned by the server:', xhr.responseText);
}
});
But still, I need to figure out how to print after data has loaded.
Well... I think I found the answer I was seeking:
$('body').on('DOMNodeInserted', 'table', function() {
$('td:visible').translate('es', 'en');
});
It seems it is working correctly.

Cannot get selected item in jquery autocomplete

Using Jquery autocomplete UI widget, I have the following code that gets a list of suburbs/postcodes via external php:
<script>
$(function() {
$("#suburb").autocomplete({
minLength:3, //minimum length of characters for type ahead to begin
source: function (request, response) {
$.ajax({
type: 'POST',
url: 'resources/php/helpers.php', //your server side script
dataType: 'json',
data: {
suburb: request.term
},
success: function (data) {
//if multiple results are returned
if(data.localities.locality instanceof Array)
response ($.map(data.localities.locality, function (item) {
return {
label: item.location + ', ' + item.postcode,
value: item.location + ', ' + item.postcode
}
}));
//if a single result is returned
else
response ($.map(data.localities, function (item) {
return {
label: item.location + ', ' + item.postcode,
value: item.location + ', ' + item.postcode
}
}));
},
select: function (event, ui) {
alert("SELECT");
$('#postCode').val("POSTCODE");
return true;
}
});
}
});
});
</script>
The autocomplete itself works well, I get the list of matches , however the 'select' part does not work, ie, I need to set another input text value to the value selected, but even in the above code, the Alert dialog does not get called - the various syntax I've seen has kind of confused me, so I'm not sure what I've done wrong here.
The selectfunction should be outside of the object that is sent to the ajax method.
Try this:
$(function() {
$("#suburb").autocomplete({
minLength:3, //minimum length of characters for type ahead to begin
source: function (request, response) {
$.ajax({
type: 'POST',
url: 'resources/php/helpers.php', //your server side script
dataType: 'json',
data: {
suburb: request.term
},
success: function (data) {
//if multiple results are returned
if(data.localities.locality instanceof Array)
response ($.map(data.localities.locality, function (item) {
return {
label: item.location + ', ' + item.postcode,
value: item.location + ', ' + item.postcode
}
}));
//if a single result is returned
else
response ($.map(data.localities, function (item) {
return {
label: item.location + ', ' + item.postcode,
value: item.location + ', ' + item.postcode
}
}));
}
});
},
select: function (event, ui) {
alert("SELECT");
$('#postCode').val("POSTCODE");
return true;
}
});
});

How To Test Unstructured Javascript/JQuery

I'm faced with trying to add testing to a lot of code like the following. I know I can use mockjax to to intercept the ajax calls. But I don't how to test the $.ajax({...}) calls in isolation. I'd appreciate a good refactoring approach, but I'd also like to avoid rewriting the entire app.
I've gotten a start in other areas using qunit, and I like it. But I'm open to other suggestions too. How should I proceed?
function submitSync(repFrom, continuousRep, storedPassword) {
// var repTriggered = false;
if (repFrom !== '' && (storedPassword !== null || storedPassword !== "")) {
var secureHome = "http://" + homeUser + ":" + storedPassword + "#" + window.location.host + "/" + homeURL;
var theSource = repFrom.split("/");
var singleDocumentReplication = (theSource.length === 5);
/*
* DELETE existing replications. There will normally be no more than 1.
* Do not delete replications for application updates.
* Note that we don't allow the user to create continuous replications.
*/
$.getJSON(currentHost + '/_replicator/_all_docs', function (data) {
$.each(data.rows, function (i, theRow) {
$.ajax({
url: currentHost + '/_replicator/' + theRow.id,
type: "GET",
dataType: 'json',
async: false,
contentType: "application/json",
success: function (doc) {
if (doc._id !== "_design/_replicator" && (typeof doc.source !== 'undefined' && !doc.source.match(onlineBase + '/' + remoteDB))) {
$.ajax({
url: "/_replicator/" + doc._id + "?rev=" + doc._rev,
type: "DELETE",
contentType: "application/json",
success: function () {
console.log('Replication deleted: ' + doc._id + '?rev=' + doc._rev);
}
});
}
}
});
});
});
if (singleDocumentReplication) {
var theDoc = theSource[4];
var repFromBase = repFrom.substr(0, repFrom.indexOf(theDoc) - 1);
$.ajax({
url: "/_replicator",
type: "POST",
data: JSON.stringify({ "source": repFromBase, "target": secureHome,
"userCtx": { "name": homeUser, "roles": ["_admin", homeUser] },
"continuous": continuousRep,
"retries_per_request": 10,
"http_connections": 3,
"doc_ids": [theDoc]
}),
contentType: "application/json",
error: function () {
dialog(libLang.noSync);
},
success: function (message) {
if (message) {
dialog(libLang.synced);
}
repTriggered = true;
}
});
} else {
$.ajax({
url: "/_replicator",
type: "POST",
data: JSON.stringify({ "source": repFrom, "target": secureHome,
"userCtx": { "name": homeUser, "roles": ["_admin", homeUser] },
"continuous": continuousRep,
"retries_per_request": 10,
"http_connections": 3
}),
contentType: "application/json",
error: function () {
dialog(libLang.noSync);
},
success: function (message) {
if (message) {
dialog(libLang.synced);
}
repTriggered = true;
}
});
}
}
}
Looks like you've got a ton of code duplication. My recommendation would be to put your ajax calls into modules and pass the $.ajax as a dependency.
So:
function myModule(ajaxDependency, anyOtherDependency) { }
This way in your unit test you simply check to make sure your dependecies behave a certain way. And it looks like it will eliminate all your DRY issues.

Categories

Resources