Jquery how to translate text date with momentjs - javascript

I have a bunch of <p>-tags which each has a date inside. Now I want to translate those to another format using momentjs but it doesn't really work.
<div class="container">
<p class="ordered">2018-10-01</p>
<p class="ordered">2018-10-02</p>
<p class="ordered">2018-10-03</p>
</div>
and my js file:
$(".ordered").each(item => {
let formatted_order_date = moment(item).locale("de").format("Do MMM");
});
Here is a JSFIDDLE
So, can someone tell me what is the issue here?

item in your example is not the datestring, but is the index.
The callback in each has two params: the index, and the item (as second): each((i,item) ...
The item then is the complete html element, so we need to get the 'value' (the inner html) out of it:
$(item).html()
$(".is-ordered").each((i,item) => {
// console.log($(item).html());
let datestring = $(item).html();
let formatted_order_date = new moment(datestring)
.locale("de")
.format("Do MMM");
console.log(formatted_order_date); // 3rd Oct
});

Instead of using item, try using $(this).
$(".ordered").each(() => {
const formatted_order_date = moment($(this).text().trim()).locale("de").format("Do MMM");
$(this).text(formatted_order_date);
});

Related

Printing to the screen using innerHTML and innerText not working with my htmlCollection

This is not a duplicate so please don't close this. I did my research and already found what is considered a duplicate and it did not answer my quesiton. I want to modify all elements with the same class name in the dom so I already know the difference between getElementById and getElementsByClassName.
I have some code that almost works. I have to take a string, convert it to a number, then convert it back to a currency based string and then replace the text withing the innerHTML on screen. In my console.log, I am getting back the exact amounts I need for all the elements with the class="lh1em". I got everything working up until the point I have to replace the text with this new variable I have created with the new and improved data. I have tried to do it with a function, without a function but in both cases, I get no results, no errors except I get correct info in the console.log.
Here is my html:
<div class="price">
<span class="label">from</span>
<span class="value"><span class="text-lg lh1em item "> $3,845.00</span>
</span>
<br>
<span class="label">from</span>
<span class="value"><span class="text-lg lh1em item "> $3,645.00</span>
</span>
</div>
and my javascript
let customPrice = document.getElementsByClassName('lh1em');
Array.from(customPrice).forEach(function(dollarAmount) {
let withoutDollar = dollarAmount.innerText.substr(1);
let withoutComa = withoutDollar.replace(",",'');
let noPointZero = withoutComa.replace(/\.00/, '');
noPointZero = Number(noPointZero);
let newDollar = noPointZero - 600;
let formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
});
let doubleOccupancyPrice = formatter.format(newDollar);
function changeText() {
document.getElementsByClassName('lh1em').innerHTML = doubleOccupancyPrice;
}
changeText();
console.log(doubleOccupancyPrice);
});
If anyone can show me what I am doing wrong, I would sure appreicate it. Thank you in advance.
Credit goes to #pilchard for helping me come up with the answer to this.
I just had to replace my function with the following code:
dollarAmount.innerHTML = doubleOccupancyPrice;
With that, I was able to get the right info both in cosole and on the dom

How to fetch the value of an attribute of an element in cypress?

I am working on cypress testing for a table in a web page. An example of the elements in the page is as follows:
<div class="MuiDataGrid-cell MuiDataGrid-cellWithRenderer" data-testid="admission-row">
<div class="MuiDataGrid-cell" role="cell" data-value="2020-11-21" data-field="admissionDate" data-rowindex="0">21-NOV-2020</div>
<div class="MuiDataGrid-cell" role="cell" data-value="2020-10-15" data-field="admissionDate" data-rowindex="0">15-OCT-2020</div>
<div class="MuiDataGrid-cell" role="cell" data-value="2020-09-07" data-field="admissionDate" data-rowindex="0">07-SEP-2020</div>
</div>
In the test that I am working on, I want to get the data-value attributes from each of the div elements and store them in a list, this is what I am trying.
let dateList = [];
cy.get("[data-testid='admission-row']").children().each((element) => {
cy.get(element).invoke("data-value").then((date) => {
dateList.push(date);
});
});
However, this is not working and I am facing an error data-value does not exist in your subject. I have also tried with cy.its instead of cy.invoke that failed as well. Any help regarding this bit of code would be incredibly helpful.
Based on #Hiram comments, the code which worked is as follows:
let dateList = [];
cy.get("[data-testid='admission-row']").children().each((element) => {
cy.get(element).invoke("attr", "data-value").then((date) => {
dateList.push(date);
});
});
You have to use .invoke('attr', 'data-value') instead of .invoke('data-value'). Reference from Cypress Docs.
let dateList = [];
cy.get("[data-testid='admission-row']").children().each((element) => {
cy.wrap(element).invoke('attr', 'data-value').then((date) => {
dateList.push(date);
});
});

How can I dynamically insert dates in dncalendar?

I've got a problem using dncalendar, hope someone will help me!
I need a simple calendar in which being able to save and recover data from a db. dncalendar seemed good, but I have now problem in dynamically insert data into it.
I post some code for clarification. I recover the dates from some input fields called .date-smart and build an array (data_note). Problem is when I want to dynamically insert this dates into object notes, without knowing how many dates I have. If I do it like in below code, everything works fine, but I do not know how to do it with a for cycle or similar. Can someone help me?
var data_note =[];
var note = [];
$(".date-smart").each(function(){
data_note.push($(this).val())
note.push("SW");
})
var my_calendar = $("#dncalendar-container").dnCalendar({
dataTitles: { defaultDate: 'default', today : 'Today' },
startWeek:'monday',
});
my_calendar.build();
my_calendar.update({
notes: [{'date': data_note[0], 'note':note[0]}, {'date': data_note[1], 'note':note[1]}];
})
Why don't just make a variable feed all data in it and then pass it to notes
Like
var data_note =[];
var note = [];
var notesArr = [];
$(".date-smart").each(function(){
data_note.push($(this).val())
note.push("SW");
notesArr.push({'date': $(this).val(), 'note': 'SW'});
})
var my_calendar = $("#dncalendar-container").dnCalendar({
dataTitles: { defaultDate: 'default', today : 'Today' },
startWeek:'monday',
});
my_calendar.build();
my_calendar.update({
notes: notesArr
})

ForkJoin() issue on Angular

Hello I am currently working on an UI and I need to print for each 'digId' a value that I retrieved in an unique JSON response.
In the case below, I have 3 incidents and I did a fork to have access to the 3 JSON response.
digId='4149';
digId2='4719';
digId3='4309';
ngOnInit(): void {
const parallel$ = Observable.forkJoin(
this.http.get('http://ninjaopsapi?tablename=REF_OPS_ALARM&babylonref=' + this.digId),
this.http.get('http://ninjaopsapi?tablename=REF_OPS_ALARM&babylonref=' + this.digId2),
this.http.get('http://ninjaopsapi?tablename=REF_OPS_ALARM&babylonref=' + this.digId3)
);
parallel$.subscribe( data => {
this.alarms = data, console.log(data);
})
}
My goal is to print the element circled in blue for example: Capture
But with this code below in my html, I retrieve the element [0] for the three incidents and I can't put an additionnal [0] to select only one.
<div *ngFor= "let alarm of alarms">
<div [(ngModel)]="digId" ngDefaultControl>
<div>{{alarm[0].alertMessage}}</div>
</div>
</div>
Is it possible to print the first element of the first element in an array when the .subscribe is done with a "forkJoin()" ?
Thank you
UPDATE
I only changed {{alarm[0][0].alertMessage}} by {{alarms[0][0].alertMessage}} and delete the loop *ngFor="let alarm of alarms
and it works well ! Thank you
You could simply do
parallel$.subscribe( data => {
this.alarms = data.map(x => x[0]);
});
<div>{{alarm.alertMessage}}</div>

too much HTML in an ajax script?

I read from this page that appending a lot of elements is bad practice and I should build up a string during each iteration of the loop and then set the HTML of the DOM element to that string. Does the same go for using too much HTML in the loop?
I have an AJAX script that parses JSON data. It requires adding data to different existing elements, like this:
$.ajax({
url: "url",
success: function (data) {
$(data.query.results.json.json).each(function (index, item) {
var title = item.title, // A,B,C or D
age = item.age,
background = item.background,
ingredient = item.Ingredient;
$('.'+ title+'_ingredient').html(''+ingredient+'')
$('.'+ title+'_age').html(''+age+'')
$('.'+ title+'_background').html(''+background+'')
});
},
error: function () {}
});
HTML:
<div class="A_ingredient"></div>
<div class="B_ingredient"></div>
<div class="C_ingredient"></div>
<div class="D_ingredient"></div>
<div class="A_age"></div>
<div class="B_age"></div>
<div class="C_age"></div>
<div class="D_age"></div>
<div class="A_background"></div>
<div class="B_background"></div>
<div class="C_background"></div>
<div class="D_background"></div>
Is it necessary to build up a string first? If so, can you show me how to do that?
It is purely about the time it takes to process calls to html() so they simply recommend you reduce the number of calls. In this case you could build them once in a loop then sets the div html once for each.
Update:
Based on your update, aside from all the extra trailing quotes you don't need to add (a string is a string is a string), your code is fine as is. You only hit each item once.
e.g.
$.ajax({
url: "url",
success: function (data) {
$(data.query.results.json.json).each(function (index, item) {
var title = item.title, // A,B,C or D
age = item.age,
background = item.background,
ingredient = item.Ingredient;
$('.'+ title+'_ingredient').html(ingredient);
$('.'+ title+'_age').html(age);
$('.'+ title+'_background').html(background);
});
},
error: function () {}
});
Note: If your item properties (Age, Background, Ingredient) are simple values (not objects or arrays), yo do not need the leading ''+s either.
Previous
Assuming you actually want to concatenate the results (you are only keeping the last ingredient at the moment), you could do something like this:
e.g.
$.ajax({
url: "url",
success: function (data) {
var ingredients = '';
$(data.query.results.json.json).each(function (index, item) {
var title = item.title;
var ingredient = item.Ingredient;
ingredients += ingredient;
});
$('.aclass').html(ingredients);
$('.bclass').html(ingredients);
$('.cclass').html(ingredients);
$('.dclass').html(ingredients);
},
error: function () {}
});
Which can be reduced to:
$('.aclass,.bclass,.cclass,.dclass').html(ingredients);
The contents of each div are identical in your example, so you only need a single string.
In this instance you would probably need some form of delimiter between ingredients, but your example is too vague.
e.g.
ingredients += ingredient + '<br/>';
In your example, you're setting the HTML on many different document elements.
If they're grouped in some way, for example all in a Div with ID #Container, you could build a string of the HTML and set the content of the whole Div at the end of it, something like this:
$.ajax({
url: "url",
success: function (data) {
var sHTML="";
$(data.query.results.json.json).each(function (index, item) {
var title = item.title,
background = item.background,
ingredient = item.Ingredient;
// not sure what your actual HTML is (div/span/td etc) but somethign like this?
sHTML+="<div>"; // an opening container for this item
sHTML+='<div class="'+title+'_ingredient">'+ingredient+'</div>')
sHTML+='<div class="'+title+'_age">'+title+'</div>')
sHTML+='<div class="'+title+'_background">'+background+'</div>')
sHTML+="</div>";
});
$("#Container").html(sHTML);
},
error: function () {}
});
Note I haven't tested this code, but you see the principal hopefully.
That is, build a string of the HTML then set one element at the end with the content.
I have done this a lot in a recent project and haven't seen any speed issues (maybe 50 'items' to set in my case).
HTML will initially look like this :
<div id="container">
</div>
Then end up like this (2 x items in this example) :
<div id="container">
<div>
<div class="<sometitle1>_ingredient">ingredient 1</div>
<div class="<sometitle1>_age">age 1</div>
<div class="<sometitle1>_background">background 1</div>
</div>
<div>
<div class="<sometitle2>_ingredient">ingredient 2</div>
<div class="<sometitle2>_age">age 2</div>
<div class="<sometitle2>_background">background 2</div>
</div>
</div>
subsequent calls will replace the element's content with new values, replacing the old items.
Building a string is, I would imagine, less processor-heavy than setting the html() on lots of elements individually. Each time you use html() I'm guessing that the browser has to go some way towards working out any knock-on effects like expanding the width of an element to accomodate it or whether events will still work as they did, etc - even if actual rendering is only run at the end of the process. This way you use html() once, although what you're setting is more complex.
Hope this helps.

Categories