How JQuery handles with getElementsByClassName iteration? - javascript

Today I was shortening my old codes and I saw this code:
$(".ceker").append("<a href='kit/");
$("#pdf").append("pdf");
$("#txt").append("txt");
$("#epub").append("epub");
$(".ceker").append("/7.");
$("#pdf").append("pdf");
$("#txt").append("txt");
$("#epub").append("epub");
$(".ceker").append("'><div class='menukitap'><div class='menuharry7 menuharresler'></div><h4>Ölüm Yadigarları İndir</h4></div></a>");
it used to output like that:
<div class="menukitap"><div class="menuharry7 menuharresler"></div><h4>Ölüm Yadigarları İndir</h4></div>
And I made it shorter like this:
function item()
{
if( $('.ceker').attr('id') == 'pdf' )
{
return "pdf";
}
if( $('.ceker').attr('id') == 'txt' )
{
return "txt";
}
if( $('.ceker').attr('id') == 'epub' )
{
return "epub";
}
}
$(".ceker").append("<a href='kit/" + item() + "/7." + item() + "'><div class='menukitap'><div class='menuharry7 menuharresler'></div><h4>Ölüm Yadigarları İndir</h4></div></a>");
This code works too, but I don't why it does. In my opinion, this code shouldn't work because the class "ceker" has already had 3 different IDs "pdf" 'txt' and "epub"
So here's my question: How JQuery handles with getElementsByClassName Iteration (answer 1)? (I do not understand how this works if( $('.ceker').attr('id') == 'pdf' ))
And here is the HTML if you need to
<nav class="menu">
<span class="ara-menu-yer">Türkçe</span>
<a><li><section id="pdf" class="ceker"></section></li></a>
<a><li><section id="txt" class="ceker"></section></li></a>
<a><li><section id="epub" class="ceker"></section></li></a>
<span class="ara-menu-yer">English</span>
<a><li><section id="ingpdf" class="cekereng"></section></li></a>
<a><li><section id="ingdoc" class="cekereng"></section></li></a>
</nav>
I'm sorry for bad spelling, grammar or vocabulary mistakes if there is. And I think that I couldn't explain my issue but I wish you can understand.

From the docs:
Get the value of an attribute for the first element in the set of matched elements.

Related

How to add HTML to a template based on an if condition?

I have an HTML template that's stored in sql as follows
<script id="Accounttmpl" type="text/x-jsrender">
<div class="authenticated" id="authenticated" >
<span class="loginWelcome">Hi </span>
<span class="loginWelcome">{{>FirstName}}</span>
<span id="Test" style="display:none">{{>(Verified)}} </span>
</div>
</script>
So, in my code in Javascript the template above gets called. However I want to add an if statement where if verified == 'false' it must display a message saying not verified.
This is my Javascript:
Success: function (result, context) {
if (result) {
$(context).html($('#Accounttmpl').render(result));
} else {
$(context).html($('#Accounttmpl').render({}));
}
}
So, in my result I get back the "verified" details, so what I tried is the following:
Success: function (result, context) {
if (result) {
if(result.Verified === 'false'){
document.getElementById("Test").html("not verified")} //however it doesn't find the "Test" id and throws an error that it cant read property of null
$(context).html($('#Accounttmpl').render(result));
} else {
$(context).html($('#Accounttmpl').render({}));
}
}
}
So, my question is how do I check the #Accounttmpl for the "Test" id so that I can add the if statement to it?
The reason why you get null is because you are trying to get the id of Test before you add it to the DOM.
Where you have:
if(result.Verified === 'false'){
document.getElementById("Test").html("not verified")
}
$(context).html($('#Accounttmpl').render(result));
Change the order round:
$(context).html($('#Accounttmpl').render(result));
if(result.Verified === 'false'){
document.getElementById("Test").html("not verified")
}
Also, you are mixing JavaScript with jQuery here:
document.getElementById("Test").html("not verified")
Either do:
document.getElementById("Test").textContent = "not verified";
Or
$("#Test").html("not verified")

how to generate different html if the given object has no results

I am talking to WP REST API and if I do have results in data object I generate HTML code to frontend, and that is working fine, but what to do, and how to generate different HTML output (for example "There is no search result") if there is not data in data object.
I try with if statement but no luck with that. I am new to coding so forgive me if this is trivial problem...
var searchVal = this.inputField.val();
$.getJSON('http://localhost:8888/wptest/wp-json/wp/v2/posts?search=' + searchVal,
data => {
this.createHtml.html(`
<h2 class="search-overlay__section-title">Posts Info</h2>
<ul class="link-list min-list">
<li>${data[0].title.rendered}</li>
</ul>
`);
});
Your code should work if its as below:
var searchVal = this.inputField.val();
$.getJSON('http://localhost:8888/wptest/wp-json/wp/v2/posts?search=' + searchVal,
data => {
if (data.length == 0) {
// no results html
} else {
this.createHtml.html(`
<h2 class="search-overlay__section-title">Posts Info</h2>
<ul class="link-list min-list">
<li>${data[0].title.rendered}</li>
</ul>
`);
}
});
Hope this helps !!
Hello guys I did a little research and found a more concise solution, Ternary Operator... sorry if I didn't say it was ES6 syntax and I used a compiler to run regular javascript in the browser
var searchVal = this.inputField.val();
$.getJSON('http://localhost:8888/wptest/wp-json/wp/v2/posts?search=' + searchVal,
data => {
this.createHtml.html(`
<h2 class="search-overlay__section-title">Posts Info</h2>
${data.length == 0 ? '<p>No Results</p>' : '<ul class="link-list min-list">'}
${data.map(item => `<li>${item.title.rendered}</li>`).join('')}
${data.length == 0 ? '</ul>' : ''}
`);
});

Matching multiple keywords using contains() in jQuery

Currently matching a specific keyword using contains(). How can i expand this to include multiple keywords?
have tried using the || (or) operator, but no joy.
<!-- Product names include Apple iPad, Acer Iconia, Lenovo Thinkpad -->
<h1 id="pbtitle">Apple iPad 3</h1>
<div class="install_option" style="display:none;">
<div style="box-sizing:border-box; float:left;">
<a href="https://www.exmaple.com/acc" target="_blank">
<h3 style="font-weight:bold;">Would you like to view accessories?</h3>
</a>
</div>
</div>
$(".install_option").each(function() {
if($("h1#pbtitle:contains:contains('Acer' || 'Lenovo' || Apple )").length>0){
$('.install_option').css('display','block');
}
});
Use JavaScript function indexOf()
Working example jsfiddle
var options = ['Acer','Lenovo','Apple']; // options that you want to look for
var text = $("#pbtitle").text(); // string where you want to look in
options.forEach( function( element ) {
if ( text.indexOf( element ) != -1 ) { // if its NOT -1 (-1 = not found)
alert( 'found' ); // then we found it .. do your magic
}
})
Do this way
if($("h1#pbtitle:contains('Acer'),h1#pbtitle:contains('Lenovo'),h1#pbtitle:contains('Apple')").length>0)
Risking being a bit out of the question scope, I guess the product list is dynamic in same kind.
In that case it will be better to add a property to the product tag like:
<h1 id="pbtitle" has_install_option="true">Apple iPad 3</h1>
var condition = $('h1#pbtitle').attr('has_install_option') == 'true';
and checking that condition in your loop.
[think of the day you will have an Apple product with install_option or an Appleseed product...]
p.s in this example it's better to place the condition out side of the loop as the condition is static in relation to the looped elements

Have both JSX and normal className together

I have a css style class that needs to be in JSX form as it depends on the state, but I also need to use style class the ordinary way for styling. How do I combine these together?
I've tried
<span className={statusColor} className="uppercase">
Which only takes into account the last class one
<span className={statusColor uppercase}>
Which obviously looks for a variable called uppercase and errors out
<span className="uppercase {statusColor}">
Neither of them work
Below is a dummied-down version of my code. What is the correct way to do this?
const Component = React.createClass({
return {
completed: false
}
},
render () {
let statusColor;
this.state.completed === true ? statusColor = "green" : statusColor = "red";
return (
<div className="status-banner">
<span className="kata-text-status">Status: <span className={statusColor} className="uppercase">{this.state.completed.toString()}</span></span>
</div>
)
}
})
Try this:
<span className={`uppercase ${statusColor}`}>
This will use an ES6 template string (`uppercase ${statusColor}`) and interpolate statusColor with ${...}.
<span className={'uppercase' + ' ' + statusColor}>
You can do it in several ways.
Firstly you can use + to concat more than one string variables and generate dynamic strings
<span className={"uppercase " + statusColor}>
Or you can use npm modules classnames.
The brackets {} translate to normal JS. So you can just use + to concatenate.
<span className={"uppercase " + statusColor}>

ng-class not working. Where did I do wrong?

I know there are many problems here listed like this. but I can't pinpoint where I did wrong..
<li ng-repeat="item in type.sub | orderBy:y" ng-click="openpic($parent.$index, $index)" ng-class="{ 'active': $parent.$index + ':' + $index == current }">
we have $scope.current variable, and a nested menu with numbering id like 1:2, 1:3, 1:4, 2:1, 2:2, 2:3 and so on.
Goal is very simple. I need to make this <li> active, if the $parent.$index:$index is equal to $scope.current. ID is set whenever openpic($parent.$index, $index) triggered. We have li.active class in css.
So, can someone please show me, what's missing in that code?
TRY 1:
Tried:
<li ng-repeat="item in type.sub | orderBy:y" ng-click="openpic($parent.$index, $index)" ng-class="{ 'active': $parent.$index + ':' + $index == $parent.current }">
Still not working.
TRY 2
I have something like this:
ng-class="{{ $parent.$index + ':' + $index == $parent.current && 'active' || '' }}"
and it shows as ng-class="active" but class attribute did not updated.
TRY 3
ng-class="{{ $parent.$index + ':' + $index == $parent.current && 'highlight' || '' }}"
it shows ng-class='highlight", but class still shows class="ng-binding ng-scope"
TRY 4
ng-class="isActive($parent.$index,$index)"
It solves the problem, but it seems a little bit overkill for a simple switch function. Any more ideas?
TRY 5
As per major-mann code suggestion that works at TRY 4, I made these adjustment, and surprisingly, it works.
ng-class="$parent.$index + ':' + $index == $parent.current && 'active' || ''"
That one works. Removed all braces completely ????
First of all make {{$parent.$index:$index}} to make sure to get the right data (I just never met such a method to data access) ;
If it's ok, then try use:
ng-class="$parent.$index:$index === current ? 'active' : ''"
Or (best way) use function for this:
ng-class="someFn($parent.$index)"
$scope.someFn = function(index){
//index, index:index, index[n] or something else;
return index === $scope.current ? 'active' : '';
};
Update:
If You want get access to parent ng-repeat, better use
<... ng-repeat="(index1, data1) in firstData">
<... ng-repeat="(index2, data2) in secondData">
<... ng-something="index1 operator index2 or function(index1, index2)">
I hope, it will help;
As pointed to in the comments, rather a non-answer, but usually it is best practice to try to keep code (even simple ternaries) inside the JavaScript blocks rather than inside the HTML. This generally makes debugging any issues you may be having infinitely easier to deal with.
So, for example, you could change your HTML to something like:
<li ng-repeat="..." ng-click="..." ng-class="isActive($parent.$index, $index)">
And in your controller, you could add something like:
$scope.menu= function isActive(pidx, idx) {
return {
active: pidx + ':' + idx === $scope.current
};
};
To achieve your desired result.
If you take this a step further, you will probably realize that it is even better to do something like
$scope.cls.menu = function(pidx, idx) {
return {
active: pidx + ':' + idx === $scope.current,
any: 'other',
dynamic: 'classes',
you: 'need'
};
}
And call the function appropriately in the view.

Categories

Resources