Extract information from all matching nodes without looping xpath - python-2.7

<ul class="products-grid">
<li class="item">
<div class="product-block">
<div class="product-block-inner">
<img src="#/producta.jpg">
<h2 class="product-name">Product A</h2>
<div class="price-box">
<span class="regular-price" id="#">
<span class="price">Rs 1,849</span>
</span>
</div>
</div>
</div>
</li>
<li class="item">
<div class="product-block">
<div class="product-block-inner">
<img src="#/productb.jpg">
<h2 class="product-name">Product B</h2>
<div class="price-box">
<span class="regular-price" id="#">
<span class="price">Rs 1,849</span>
</span>
</div>
</div>
</div>
</li>
</ul>
I am at this moment scraping the item in a loop.
products = response.xpath('//ul[#class="products-grid"]//li//div[#class="product-block"]//div[#class="product-block-inner"]').extract()
After getting the product-block-inner node, I save it into products and then I will have to loop like
for product in products:
// parse the div.product-block-inner further deep down
// to get name, price, image etc
// and save it to a dict and yeild
pass
Is this possible that i get text, href for all div.product-block-inner in the final list without looping

Yes, but it's very confusing, for example you could try this:
products = response.xpath(
'//ul[#class="products-grid"]//li//div[#class="product-block"]//div[#class="product-block-inner"]'
).css(
'.product-name a::attr(href), .product-name a::text, .price::text'
).extract()
but I would suggest to always loop (btw, why do you call extract() when you assign it to products?)
products = response.xpath(
'//ul[#class="products-grid"]//li//div[#class="product-block"]//div[#class="product-block-inner"]'
)
for product in products:
yield {'name': product.css('.product-name a::text').extract_first()
'url': product.css('.product-name a::attr(href)').extract_first()
'price': product.css('.price::text').extract_first()}
(I've used css selectors in this case because the equivalent xpaths are longer, but the same can also be achieved using xpath)

Related

How to loop over Chart.js with Django list view

I am using a Django List View, and I am trying to iterate through multiple objects and display percentage values in a Chart.JS gauge.
However, although I am iterating the names of the gauge id's by using a for loop counter, I am only ever getting the first iteration of the chart.js object rendering on my screen. My initial thoughts are that similar to how I am dynamically creating new canvas ids for the chart.js objects, I should be doing a similar thing for the variable I am trying to pass into the chart object e.g. reduction overall, but I am not having any luck. Your feedback is welcome.
Views.py
class PerformanceDetailView(ListView):
template_name = 'performance_detail.html'
model = Performance
context_object_name = 'performance'
def get_queryset(self, **kwargs):
code = self.kwargs.get('code')
return Performance.objects.filter(code=code)
Performance_detail.html
<section class="projects pt-4 col-lg-12">
{% for item in performance %}
<div class="container-fluid pt-2 col-lg-12">
<!-- Project--><div class="project" >
<div class="row bg-white has-shadow" style="height: 14rem">
<div class="left-col col-lg-2 d-flex align-items-center justify-content-between">
<div class="project-title d-flex align-items-center">
<div class="has-shadow"><img src="{% static 'img/avatar-2.jpg' %}" alt="..." class="img-fluid"></div>
</div>
</div>
<div class="right-col col-lg-2 align-items-center vertical-center">
<div class="text">
<h3 class="h2 pt-2">{{item.brand}} {{item.style}}</h3>
<p class="text-muted">{{item.package_type| capfirst}} package, round {{item.testing_round}}</p>
<p class="text-muted">Item size: {{item.size}}</p>
</div>
</div>
<div class="right-col col-lg-8 align-items-center vertical-center">
<div class="row mt-5">
<div class="col-md-3">
<div class="gauge-container">
<canvas id="gauge1-{{ forloop.counter }}" class="gauge-canvas"></canvas><span id="gauge1Value-{{ forloop.counter }}" class="gauge-label"></span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{{ item.reduction_overall|json_script:"reduction_overall" }}
{{ for_loop_counter|json_script:"for_loop_counter" }}
{% endfor %}
</section>
{% endblock content %}
Block JS within package_detail.html
<!-- Gauge.js-->
<script src="{% static 'vendor/gaugeJS/gauge.min.js' %}"></script>
<script>
$(function () {
var reduction_overall = JSON.parse(document.getElementById('reduction_overall').textContent);
var for_loop_counter = JSON.parse(document.getElementById('for_loop_counter').textContent);
// Gauges
var gauge1 = document.getElementById('gauge1-'+for_loop_counter);
opts.colorStop = "#864DD9";
var gaugeObject1 = new Donut(gauge1).setOptions(opts);
gaugeObject1.maxValue = 100; // set max gauge value
gaugeObject1.setMinValue(0); // set min value
gaugeObject1.set(reduction_overall); // set actual value
gaugeObject1.setTextField(document.getElementById("gauge1Value-" + for_loop_counter));
});
</script>
{% endblock js %}
This was solved by including the JavaScript in the main block content and dynamically naming the gauge elements themselves.
var func_name = "container-{{forloop.counter}}";
func_name = new Donut(gauge1).setOptions(opts);
I posted a full example to a similar problem here Chart JS and Django loop

Foundation 6 deep linking nested tabs

Hej all !
As the title of the subject suggest, I wonder if it's possible to have deep linking that works on nested tabs.
I mean, if I use only one tabs container, it works fine, but I don't know how to deep link to a tab inside a parent tab. It should first open the parent tab and then display the goal child tab.
Is it possible using Foundation 6 deep-linking please (without hacks) ?
Let's say we have this code :
<div>
<ul class="tabs" data-tabs id="tabs" data-deep-link="true">
<li class="tabs-title is-active">Content 1</li>
<li class="tabs-title">Content 2</li>
</ul>
</div>
<div class="tabs-content" data-tabs-content="tabs">
<div class="tabs-panel is-active" id="tab1">
My Content 1
</div>
<div class="tabs-panel" id="tab2">
<ul class="tabs" data-tabs id="tab2-tabs" data-deep-link="true">
<li class="tabs-title is-active">Content 2-1</li>
<li class="tabs-title">Content 2-2</li>
</ul>
<div class="tabs-content" data-tabs-content="tab2-tabs">
<div class="tabs-panel is-active" id="tab2-tab1">
My Content 2-1
</div>
<div class="tabs-panel" id="tab2-tab2">
My Content 2-2
</div>
</div>
</div>
</div>
How can I open "My Content 2-2" using deep-linking please ?

RIDE Robot framework Select from dynamic list

I am trying to choose an element("Classic") from a dynamic dropdown list. Problem is that word Classic contains 2 elements.
Html page is:
<ul id="dynamic-14" class="results" role="list">
<li class="results-dept result">
<div dynamic-102" class="results" role="option">
<span class="match"/>
</div>
</li>
<li class="results-dept result">
<div dynamic-12" class="results" role="option">
<span class="match"/>
Classic
</div>
</li>
<li class="results-dept result">
<div dynamic-1022" class="results" role="option">
<span class="match"/>
Classic numbers
</div>
</li>
I tried to do it with xpath using:
//ul[#class="results"] //div[contains(.,'Classic')]
but it gives me back 2 values so robot framework can't choose one I need.
user normalize-space() function to get rid of the leading and trailing whitespace.
//ul[#class="results"] //div[ normalize-space(.)='Classic']

Jquery Mobile - Several items from listview on same line

I am encountering an issue with Jquery Mobile :
I want to display a grid of items using three columns. Each new item must be displayed next to the previous one and begin a new line after the third column.
To give you an example, I want something like this : JSFiddle
But my items have to be items from a splitButtonList (an icon with labels on the left and a clickable button on the right) instead of the blocks from the previous example.
The problem is : when I use the kind of code shown below, each new item is display at the bottom of the previous one, like in a list. I cannot manage to display it using my three columns grid pattern JSFiddle.
<body>
<div data-role="page" data-theme="c" id="projets">
<div data-role="header" data-position="fixed" data-theme="f" data-tap-toggle="false" id="banniere">
</div>
<div data-role="content" id="content">
<div class="ui-grid-b">
<ul data-role="listview" data-split-icon="star" data-split-theme="a" class="listview">
<li>
<a href="projects.html">
<img src="img/icon/file.png" />
<h3>A label</h3>
<p>Another one</p>
<p>And finally another one</p>
</a>
Plop
</li>
<li>
<a href="projects.html">
<img src="img/icon/file.png" />
<h3>A label</h3>
<p>Another one</p>
<p>And finally another one</p>
</a>
Plop
</li>
</ul>
</div><!-- /grid-b -->
</div>
<div data-role="footer" data-position="fixed" data-theme="f" data-tap-toggle="false" id="footer">
</div>
</div>
</body>
Do you have any idea of what to do ? Using CSS maybe ? Any clue would be very precious for me. Thank you
How about this? JSFiddle
You were basically missing the 3 child containers of the grid:
<div class="ui-grid-b">
<div class="ui-block-a">Listview 1 goes here...</div>
<div class="ui-block-b">Listview 2 goes here...</div>
<div class="ui-block-c">Listview 3 goes here...</div>
</div><!-- /grid-b -->
So, as you can see you will need three different listview.
Hope this helps!

Display element in form using Zurb Foundation

I'm using the CSS Framework Foundation and when I write the following code:
<div class="row">
<div class="two mobile-one columns"><label for="invoiceterm-summary" class="right inline">Become late <span class="required">*</span></label></div>
<div class="ten mobile-three columns"><input class="one" id="invoiceterm-late" name="invoiceterm[late]" type="text" value=""> days after invoice sent</div>
</div>
​
I get this :
But I want to display the text "days after invoice sent" like this:
You should place all of these elements into a single:
<div class="row">
<div class="twelve mobile-four columns"></div>
</div>
Otherwise it is behaving correctly, stacking the columns as the screen size is reduced.
I had to remove the display: block property from the css definition of the input[type="text"] on the foundation.css file