Change image on json property when appending template - javascript

An image can have [1,2,3,4] states (placeholder, processing, accepted, rejected) in a JSON format. I am figuring out a function to check the property and select the right image to place in the Mustache HTML.
I tried the following:
for (let i=0;i<101;i++) {
var output = Mustache.render(template, view[i]);
$('#entryTable tbody').append(output);
if (view[i].status == 2) {
this.getElementById('picture1').src= 'img/analyzing.png';
} else if (view[i].status == 3) {
this.getElementById('picture1').src= 'img/irrelevant.png';
console.log(this)
} else if (view [i].status == 4) {
this.getElementById('picture1').src= 'img/relevant.png';
}
But 'this' refers to the document and not the image -> it changes only the first image (for all entries, repeatedly) that appears.
Next, I tried:
for (let i=0;i<101;i++) {
var output = Mustache.render(template, view[i]);
$('#entryTable tbody').append(function() {
//the default image in the template is state 1, hence it checks for state 2 and above
if (view[i].state == 2) {
this.getElementById('picture1').src= 'img/analyzing.png';
} else if (view[i].state == 3) {
this.getElementById('picture1').src= 'img/irrelevant.png';
console.log(this)
} else if (view [i].state == 4) {
this.getElementById('picture1').src= 'img/relevant.png';
}
return output;
});
Which seems(?) to work but only appends one entry.
I am not experienced with 'this', how would I get it to the right context/scope to change the entry specific image?

Solved
if (view[i].state === 1) {
$("#entryTable tbody tr .status1").eq(i).attr("src", "img/analyzing.png");
} else if (view[i].state === 3) {
$("#entryTable tbody tr .status1").eq(i).attr("src", "img/irrelevant.png");
} else if (view[i].state === 4) {
$("#entryTable tbody tr .status1").eq(i).attr("src", "img/relevant.png");
}
}

Related

Is it possible to call a method from a class in an HTML event like 'onblur'?

I got a little problem that I can't solve...
I usually check my form like this:
function checkFirst(field) {
if (field.value.length < 2 || !regLetters.test(field.value)) {
//do something
} else {
//do something else
firstNameOk = true;
}
}
and on the HTML side with onblur="checkFirst(this)".
Now I'm using OOP and I can't use my methods in onblur and I don't know how I could call the class in the onblur HTML attribute...
I already got a solution to work around this without using onblur in HTML and in my case I'd like to know if it's possible or not.
Anyone to help me please?
Edit:to avoid people telling me to use addEventlistener i show you my solution that works fine but not the one i wanted to use...
this.data.forEach(item => item.addEventListener('blur', function () {
console.log(item.id)
// check first name field //
if (item.id === "first") {
if (item.value.length < 2 || !this.regLetters.test(item.value)) { // if this field length =
this.highlightField(item, true);
} else {
this.highlightField(item, false);
this.errorMessagesReset(item);
this.firstNameOk = true;
}
// check last name field //
} else if (item.id === "last") {
if (item.value.length < 2 || !this.regLetters.test(item.value)) {
this.highlightField(item, true);
} else {
this.highlightField(item, false);
this.errorMessagesReset(item);
this.lastNameOk = true;
}
// check email field //
} else if (item.id === "email") {
if (item.value.length < 2 || !this.regmail.test(item.value)) {
this.highlightField(item, true);
} else {
this.highlightField(item, false);
this.errorMessagesReset(item);
this.emailOk = true;
}
// check textarea field //
} else if (item.id === "message") {
if (item.value.length < 1 || item.value > 100) { // if length of item is sup or equal to 1 and
this.highlightField(item, true);
} else {
this.highlightField(item, false);
this.errorMessagesReset(item);
this.messageOk = true;
}
}
}.bind(this))); ```
It should be a static function that belongs to the class then. That way you can call it directly.

Javascript element ID visible but not accessible on keyup event

I am trying to cycle through a list of custom autocomplete options using the arrow keys in JavaScript. I am attempting to do this by iterating through the options and adding a "selected" ID to the option currently selected. I've run in to a problem where, although the "selected" ID of the option currently selected is visible (if you log it out, you can see the ID), the ID is inaccessible (trying to log out element.id returns an empty string).
Here is the code:
SearchBox.prototype.handleOptionNavigation = function() {
_this.inputElement.addEventListener("keyup", function(event) {
var options = _this.getOptions();
if (event.key === "ArrowUp") _this.moveSelectedUp();
if (event.key === "ArrowDown") _this.moveSelectedDown();
});
}
SearchBox.prototype.getOptions = function() {
return Array.from(document.getElementsByClassName("result-item"));
}
SearchBox.prototype.getSelectedIndex = function() { //here is the problem
var options = _this.getOptions();
if (options.length === 0) return;
console.log(options[2]);
//this returns <li class="result-item" id="selected">...</li>
console.log(options[2].id);
//this returns an empty string
return 1;
//this function is supposed to return the index of the element currently selected;
//I am returning 1 just to see a selected element on the screen.
}
SearchBox.prototype.moveSelectedDown = function() {
var options = _this.getOptions();
if (options.length === 0) return;
var selectedIndex = _this.getSelectedIndex();
if (selectedIndex === -1) {
options[0].id = "selected"
} else if (selectedIndex === (_this.maxResults - 1)) {
options[0].id = "selected"
options[options.length - 1].removeAttribute("id");
} else {
console.log("we are moving down");
options[selectedIndex + 1].id = "selected";
options[selectedIndex].removeAttribute("id");
}
}
SearchBox.prototype.moveSelectedUp = function() {
var options = _this.getOptions();
if (options.length === 0) return;
var selectedIndex = _this.getSelectedIndex();
console.log(selectedIndex);
if (selectedIndex === -1) {
options[options.length - 1].id = "selected";
} else if (selectedIndex === 0) {
options[0].removeAttribute("id");
} else {
options[selectedIndex - 1].id = "selected";
options[selectedIndex].removeAttribute("id");
}
}
The idea is that, with each press of the up or down arrows, a different element in the list of complete options will become highlighted. However, because I can't seem to access the id of the selected element, it gets stuck and the moveSelectedUp/moveSelectedDown functions don't work.
Does anyone know what is going on here?
Thank you!
Not quite sure what you are trying to achieve in your method SearchBox.prototype.getSelectedIndex, but it is always returning 1, how is that supposed to help ?
I've updated your method so that it returns the real index and it seems to work fine, see the fiddle below :
https://jsfiddle.net/c2p1aayh/

How to add different classes to template element?

In my JSON file I have 7 objects, where first 3 of them have "is_read" attribute == 1, and last 4 have "is_read" == 0.
I add rows, using a template and want to give tr different classes according to their "is_read" value (".news_read" for "is_read" == 1 and ".news_unread" for "is_read" == 0).
However, I end up with 7 rows that all have "news_unread" class. Though, console.log shows that I have 3 "newsData.get('is_read') == 1" and 4 "newsData.get('is_read') == 0" objects.
I wonder how to create rows with different classes. I tried to do newsRow.addClass, but the error message says that an object <tr><td>...</td></tr> (newsRow template) can't have a method addClass.
render: function() {
news.fetchMyNews();
for (var i = 1; i <= news.length; i++) {
var newsData = news.get(i);
var newsRow = JST["news/row"](newsData.attributes);
$("#news_tbody").append(newsRow).first('tr').attr("class",function(){
if (newsData.get('is_read') == 1)
return "news_read";
else if (newsData.get('is_read') == 0)
return "news_unread";
});
}
}
You wrote:
I tried to do newsRow.addClass, but the error message says that an object ... (newsRow template) can't have a method addClass.
But I can't find addClass in your example code:
$("#news_tbody").append(newsRow).first('tr').attr("class",function(){
if (newsData.get('is_read') == 1)
return "news_read";
else if (newsData.get('is_read') == 0)
return "news_unread";
});
I just can advice you to try this code(use addClass, instead of attr and add blocks in if statement):
$("#news_tbody").append(newsRow).first('tr').addClass(function(){
if (newsData.get('is_read') === 1){
return "news_read";
} else if (newsData.get('is_read') === 0) {
return "news_unread";
}
});
As #Pinal suggested, I used addClass instead.
However, after append(newsRow) I used .children('tr') and it worked fine.
$("#news_tbody").append(newsRow).children('tr').addClass(function(){
if (newsData.get('is_read') === 1){
return "news_read";
} else if (newsData.get('is_read') === 0) {
return "news_unread";
}
});

Simple If statement for Javascript(jQuery)

I am trying to wrap my head around if statements. I am new to this.
I have a pretty simple script pulling data(text) from a html5 data attribute.
var $datatext = $(this).data('explain');
Now I want an if statement when html5 attribute data-explain is missing or empty.
var $success = if ($datatext < 0) {
// show some other text, maybe? =
$(this).text('Fail');
} else {
// show original, maybe? =
$(this).text($datatext);
}
Again, hard time wrapping my head around it. Ohhh these ifs.
That should work:
if (typeof $datatext !== 'undefined' && $datatext.length > 0) {
$(this).text($datatext);
} else {
$(this).text('Fail');
}
check for the length not for the data in $datatext rewrite your code like this
if ($datatext.length > 0) {
// show original, maybe? =
$(this).text($datatext);
} else {
// show some other text, maybe? =
$(this).text('Fail');
}
You can do it this way,
Live Demo
$('.someclass').each(function() {
if(typeof this.attributes['data-explain'] != 'undefined')
{
alert(this.id + ": explain exists");
explain = $.trim(this.getAttribute('data-explain'))
if(explain.length > 0)
alert(explain);
else
alert("no value for explain");
}
else
alert(this.id + ": explain does not exists");
});​

problem in run some js codes after click

why after search and click on result search and click on plus(button add input) in the example on part Adding input, Date formating($('.find_input').delegate('input.date:text', 'keyup', ....) and normal number formatting($('.find_input').delegate('input.numeric:text','keyup',...) not work.
EXAMPLE: http://www.binboy.gigfa.com/admin/tour_foreign/insert_foreign
Js full code: http://jsfiddle.net/ZpDDR/
...
///// Date formating /////////////////////////////////////////////////////////////////////////////////////////
$dateSet = 0;
$monthSet = 0;
$yearSet = 0;
$('.find_input').delegate('input.date:text', 'keyup', function () {
$val = $(this).val().replace(/[^\d]+/g, "").match(/\d{1,12}$/);
if($val == null) {
return;
} else {
$val = $val.join("");
}
if($(this).val().match(/\d{4,}$/) && $val.length%2 == 0) {
$val = $val.match(/\d{2}/g);
if($yearSet < $monthSet) {
if($val.length == 4) {
$(this).val($val.join("").replace(/(\d{2})(\d{2})(\d{4})$/,'$3/$1/$2'));
$yearSet++;
} else if($val.length == 6){
$(this).val($val.join("").replace(/(\d{4})(\d{2})(\d{2})(\d{4})$/,'$4/$2/$3'));
$yearSet++;
}
} else {
if($monthSet < $dateSet) {
$(this).val($val.join("").replace(/(\d{4})(\d{2})(\d{2})(\d{2})$/,'$1/$4/$3'));
$monthSet++;
} else {
if($val.length == 2) {
$(this).val($val.reverse().join("/"));
$dateSet++;
$monthSet++;
} else {
$(this).val($val.join("").replace(/(\d{4})(\d{2})(\d{2})(\d{2})$/,'$1/$2/$4'));
$dateSet++;
}
}
}
}
});
///normal number formatting/////////////////////////////////////////////////////////////////////////////////////////
$('.find_input').delegate('input.numeric:text','keyup',function () {
$val = $(this).val().match(/[0-9]/g).reverse().join("").match(/[0-9]{1,3}/g).join(",").match(/./g).reverse().join("");
$(this).val($val)
});
The problem is that the element that you're delegating from,.find_input, doesn't exist yet when you're setting up the delegation function. delegate allows for defining event handlers for elements that aren't created yet, but only elements that match the second selector E.g., $('#must-exist-now').delegate('.can-be-created-later', ...);
I'm not sure if I described that well, but the solution is to change your statement to delegate from something that already exists on DOM load. For example: $(document).delegate('input.date:text', ...).

Categories