iterating number type in express-edge? - express

isn't it possible to itereate through a number type variable in express-edge? On their official docs they mentioned iteration of objects and arrays and when I tried to iterate a number type variable it didn't worked (i mean like a simple loop, will run for n times)
so basically i'm trying to impelment a pagination, my controller for this look something like this:
// get total documents in the Posts collection
const count = await Posts.countDocuments();
const tpgs = Math.ceil(count / limit);
// return response with posts, total pages, and current page
res.render("index",{
psts: posts,
totalPages: tpgs,
currentPage: page
});
and the html (with express-edge) looks something like this:
#if(totalPages > 0)
<nav aria-label="Page navigation example">
<ul class="pagination">
#each(p in totalPages)
#if(p == 1)
<li class="page-item disabled">
<a class="page-link" href="#" tabindex="-1" aria-disabled="true">Previous</a>
</li>
#else
<li class="page-item"><a class="page-link" href="posts/{{ p - 1}}">Previous</a></li>
#endif
#if(p == currentPage)
<li class="page-item active" aria-current="page">
<a class="page-link" href="{{ p }}">{{ p }}</a>
</li>
#else
<li class="page-item"><a class="page-link" href="posts/{{ p }}">{{ p }}</a></li>
#endif
#if(p == totalPages)
<li class="page-item disabled">
<a class="page-link" href="posts/{{ p + 1}}">Next</a>
</li>
#else
<li class="page-item">
<a class="page-link" href="posts/{{ p + 1}}">Next</a>
</li>
#endif
#endeach
</ul>
</nav>
#endif

Related

Space disabled on concatenation

I have an array which looks like this
skills: [
"HTML5",
"CSS3",
"SCSS",
"Bootstrap",
"JavaScript",
"Vue.js",
"PHP",
"MySQL",
"Symfony"
]
And in my template I'm doing something like
<ul>
<li v-for="(skill,index) of skills" :key="index">{{ skill + ', '}}</li>
</ul>
But what I get is
HTML5,CSS3,SCSS,Bootstrap,JavaScript,Vue.js,PHP,MySQL,Symfony,
How do I able the spaces?
Btw is there a better way to concatenate the elements of my array? I first used join() like that
<ul>
<li v-for="(skill,index) of skills.join(', ')" :key="index">{{ skill }}</li>
</ul>
But not only the spaces are still disabled but it returns every character of my elements, I don't know why
Like
<ul data-v-c226fde6="">
<li data-v-c226fde6="">H</li>
<li data-v-c226fde6="">T</li>
<li data-v-c226fde6="">M</li>
<li data-v-c226fde6="">L</li>
<li data-v-c226fde6="">5</li>
<li data-v-c226fde6="">,</li>
<li data-v-c226fde6=""> </li>
<li data-v-c226fde6="">C</li>
<li data-v-c226fde6="">S</li>
<li data-v-c226fde6="">S</li>
<li data-v-c226fde6="">3</li>
...
EDIT: otherwise what I could just do is
<ul>
<li v-for="(skill,index) of skills" :key="index">{{ skill + ','}}</li>
</ul>
And then adding some padding-right to the li but I don't know if it's good practice + I don't know how I would remove the comma after the last element
Inside html template such as li you have to specify space characters using ;
<ul>
<li v-for="(skill,index) of skills" :key="index">{{ skill + ','}} </li>
</ul>
also checkout https://www.w3schools.com/html/html_entities.asp
to learn more about HTML entities
With that code you will get a list of <li></li> elements with each skill looking like this:
<li>HTML5,</li><li>CSS3,</li><li>...
just add a class or even a style with a margin to the right to add a little space between the elements either:
<ul>
<li v-for="(skill,index) of skills" style="margin-right: 5px" :key="index">{{ skill }}</li>
</ul>
better:
<ul>
<li v-for="(skill,index) of skills" class="class-with-some-margin-right" :key="index">{{ skill }}</li>
</ul>
You can add the ', ' after each item using CSS like so:
var example1 = new Vue({
el: '#example-1',
data: {
skills: ["HTML5", "CSS3", "SCSS", "Bootstrap", "JavaScript",
"Vue.js", "PHP", "MySQL", "Symfony", ]
}
})
/* styling help:
Q: https://stackoverflow.com/questions/1517220/
A: https://stackoverflow.com/a/1517228/7505395 */
#example-1 {
display: inline;
list-style: none;
}
#example-1 li {
display: inline;
}
#example-1 li:after {
content: ", ";
}
#example-1 li:last-child:after {
content: "";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<ul id="example-1">
<li v-for="(sk, idx) in skills" :key="idx">{{ sk }}</li>
</ul>
This answer incorporates it into Vue, for the pure css answer, go here.
As always you can also combine normal text inside Vues {{}} like so : {{ skill + ', ' }} - not sure if thats helpfull though as it applies to all replacement and you end up having a trailing ,

Prestashop: Hide categories without products

I would like to know if there's a way to hide categories whose sub-categories' products are out of stock.
The file with the code to show the categories is "ps_mainmenu.tpl", whose code is attached
Thanks in advance
Ive tried with some modules like "block-categories-with-counter" but it doesn't work
{assign var=_counter value=0}
{function name="menu" nodes=[] depth=0 parent=null}
{if $nodes|count}
<ul class="top-menu top-menu--level-{$depth}" {if $depth == 0}id="top-menu"{/if} data-depth="{$depth}">
{foreach from=$nodes item=node}
<li class="category-custom category-custom--level-{$depth} {$node.type}{if $node.current} current {/if}" id="{$node.page_identifier}">
{assign var=_counter value=$_counter+1}
<a
class="{if $depth >= 0}dropdown-item{/if}{if $depth === 1} dropdown-submenu{/if}"
href="{$node.url}" data-depth="{$depth}"
{if $node.open_in_new_window} target="_blank" {/if}
>
{if $node.children|count}
{* Cannot use page identifier as we can have the same page several times *}
{assign var=_expand_id value=10|mt_rand:100000}
<span class="float-xs-right hidden-md-up">
<span data-target="#top_sub_menu_{$_expand_id}" data-toggle="collapse" class="navbar-toggler collapse-icons">
<i class="material-icons add"></i>
<i class="material-icons remove"></i>
</span>
</span>
{/if}
{$node.label}
</a>
{if $node.children|count}
<div {if $depth === 0} class="popover sub-menu js-sub-menu collapse"{else} class="collapse"{/if} id="top_sub_menu_{$_expand_id}">
{menu nodes=$node.children depth=$node.depth parent=$node}
</div>
{/if}
</li>
{/foreach}
</ul>
{/if}
{/function}
<div class="menu js-top-menu position-static hidden-sm-down" id="_desktop_top_menu">
{menu nodes=$menu.children}
<div class="clearfix"></div>
</div>
You need to remove empty category in the SQL query, so in your php wrap your code with something like that :
$count = Db::getInstance()->getValue('SELECT COUNT(cp.id_category) FROM '._DB_PREFIX_.'category_product cp, '._DB_PREFIX_.'product pr WHERE cp.id_category = '.$id_current_category .' AND cp.id_product = pr.id_product AND pr.active = 1' );
if($count>0)
{
//your actual code to get the category
}

Getting nested <li> tags also.....just need the direct <li> item

I have a page structure where it includes hyperlinks with different levels of nested list items. I am writing the xpath for just the second nested list items(level 2) but it is also giving me all the list items below level 2(level 3 or below), which i don't need. It's getting really frustrating now because I have tried different xpaths and cssSelectors, everytime it is taking the level 3 list items along with level 2.
The page structure is exactly like following:
<div>
<ul class="menuBar_menu_lvl_0">
<li class="item_lvl_1">
<li class="item_lvl_1">
<ul class="menu_lvl_1">
<li class="item_lvl_2"></li>
<li class="item_lvl_2"></li>
<li class="item_lvl_2">
<ul class="menu_lvl_2">
<li class="item_lvl_3"></li>
<li class="item_lvl_3"></li>
<li class="item_lvl_3"></li>
</ul>
</li>
</ul>
<li class="item_lvl_1">
<li class="item_lvl_1">
xpath = //ul[#class="menuBar_menu_lvl_0"]//li[#class="item_lvl_1"]//ul[#class="menu_lvl_1"]//li[#class="item_lvl_2"]
This is also giving me item number 3 elements along with item level 2. I want to get each level item correctly and separately. Anybody's help would be highly appreciated
Welcome to SO.
Here is the sample that used.
<html>
<body>
<div>
<ul class="menuBar_menu_lvl_0">
<li class="item_lvl_1">
<li class="item_lvl_1">
<ul class="menu_lvl_1">
<li class="item_lvl_2">Level1-li1</li>
<li class="item_lvl_2">Level1-li2</li>
<li class="item_lvl_2">
<ul class="menu_lvl_2">
<li class="item_lvl_3">Level2-li1</li>
<li class="item_lvl_3">Level2-li2</li>
<li class="item_lvl_3">Level2-li1</li>
</ul>
Level1-li3
</li>
</ul>
<li class="item_lvl_1">
<li class="item_lvl_1">
</ul>
</div>
</body>
</html>
And below is the xpath
//ul[#class='menu_lvl_1']//li[not(parent::ul[#class='menu_lvl_2'])]
Here is the output:
Here is the method to get the text from parent element only.
def get_text_exclude_children(element):
return driver.execute_script(
"""
var parent = arguments[0];
var child = parent.firstChild;
var textValue = "";
while(child) {
if (child.nodeType === Node.TEXT_NODE)
textValue += child.textContent;
child = child.nextSibling;
}
return textValue;""",
element).strip()

TYPO3 - TypoScript TMENU ACT-object before NO-object

I'm trying to find out how to put a TMENU: .ACT-object before a TMENU: .NO-object, since I'm trying to achieve a Bootstrap 3.3.7 dropdown menu structure with the active item as leading <li>-element.
Currently I'm stuck on this part and I hope anyone can get me started to finish this structure. The structure I'm trying to achieve is the following:
<ul class="nav navbar-nav navbar-right pull-right" role="menu">
<li class="dropdown language-menu lang eng">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
<span>English</span>
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li class="lang fr"><span>Français</span></li>
<li class="lang de><a><span>Deutsch</span></a></li>
<li class="lang es><a><span>Español</span></a></li>
<li class="lang pt><a><span>Portugues</span></a></li>
<li class="lang nl><a><span>Nederlands</span></a></li>
</ul>
</li>
</ul>
The only thing that goes wrong at the moment, is that the TMENU .ACT-object is appending the TMENU: .NO-object. It is being put insite the <ul class="dropdown-menu">-element.
The TypoScript I am using:
20 = HMENU
20 {
special = language
special.value = 0,1,2,3,4,5
current = 1
wrap = <ul class="nav navbar-nav navbar-right pull-right" role="menu">|</ul>
1 = TMENU
1 {
wrap = <ul class="dropdown-menu">|</ul>
NO = 1
NO {
allWrap = <li class="lang eng">|</li> || <li class="lang nl">|</li> || <li class="lang fr">|</li> || <li class="lang de">|</li> || <li class="lang es">|</li> || <li class="lang pt">|</li>
ATagParams =
ATagBeforeWrap = 1
linkWrap = <span>|</span>
}
#ACT < .NO
ACT = 1
ACT {
allWrap = <li class="dropdown language-menu lang eng">|</li>
}
}
}
I have tried a lot the last two days and I'm hoping anyone can help me out, or at least get me started so I know where my mistakes are.
Thanks a lot!
in general ACT is put inline amongst the NO menu items. to split it up so you have the ACT separated in front of the other NO items you need to render the menu two times: first only the ACT item(s) followed by the NO items.
as you want to have one UL-tag around it I would try a COA with that UL-wrap and then two menus where the first one only renders ACT with their LI-wrap and the second only the NO with their LI-wrap.
20 = COA
20 {
wrap = class="nav navbar-nav navbar-right pull-right" role="menu">|</ul>
10 = HMENU
10 {
special = language
special.value = 0,1,2,3,4,5
current = 1
1 = TMENU
1 {
ACT = 1
ACT.allWrap (
<li class="dropdown language-menu lang eng">|</li> ||
<li class="dropdown language-menu lang nl">|</li> ||
<li class="dropdown language-menu lang fr">|</li> ||
<li class="dropdown language-menu lang de">|</li> ||
<li class="dropdown language-menu lang es">|</li> ||
<li class="dropdown language-menu lang pt">|</li>
)
NO.doNotShowLink = 1
}
}
20 < .10
20 {
ACT.doNotShowLink = 1
NO >
NO = 1
NO {
allWrap (
<li class="lang eng">|</li> ||
<li class="lang nl">|</li> ||
<li class="lang fr">|</li> ||
<li class="lang de">|</li> ||
<li class="lang es">|</li> ||
<li class="lang pt">|</li>
)
ATagParams =
ATagBeforeWrap = 1
linkWrap = <span>|</span>
}
}
Based on Bernd Wilke's answer this is what finally worked for me:
lib.menuLanguage = COA
lib.menuLanguage {
10 = HMENU
10 {
special = language
special.value = 0,1
1 = TMENU
1 {
ACT = 1
ACT {
linkWrap = <li class="extra">| <b class="caret"></b><ul class="dropdown-menu">
doNotLinkIt = 1
stdWrap {
override = EN || DE
}
}
NO = 1
NO.doNotShowLink = 1
}
}
20 < .10
20.1 {
ACT >
NO >
NO = 1
NO {
doNotLinkIt = 1
linkWrap = <li>|</li>
stdWrap {
override = EN || DE
typolink {
parameter.data = page:uid
additionalParams = &L=0 || &L=1
ATagParams = hreflang="en-GB" || hreflang="de-DE"
addQueryString = 1
addQueryString.exclude = L,id,no_cache
addQueryString.method = GET
no_cache = 0
}
}
}
}
wrap = |</ul></li>
}
with this template:
<ul class="nav navbar-nav navbar-right">
<f:cObject typoscriptObjectPath='lib.menuLanguage' />
</ul>

index of matching items in parent element even if they're in other child containers

I need to get the index of the li.play relevant to the ul.showreel_thumbnails. Is this even possible? All i seem to get is the li index inside ul.row
<ul class="showreel_thumbnails">
<li>
<ul class="row">
<li class="play_video">item</li>
<li class="play_video">item</li>
<li class="play_video">item</li>
</ul>
</li>
<li>
<ul class="row">
<li class="play_video">item 4</li>
<li class="play_video">item</li>
</ul>
</li>
</ul>
so if item 4 is clicked it should give me the index of 4 etc...
best, Dan.
It may not be valid HTML but here's how it would work (with JQuery):
function FindMyCount()
{
var item_count = 0;
$("#showreel_thumbnails li").each(function() {
++item_count;
if($(this).hasClass("igotclicked"))
return false;
});
return item_count;
}
$("#showreel_thumbnails li").click(function() {
$(this).addClass("igotclicked");
var myCount = FindMyCount(); // 1 - the # of li's under the showreel piece
$(this).removeClass("igotclicked");
// Do what you want here.
});