jQuery update data attr for element - html

So I have list of items and I need to add "data-index" for each element, index for first three elements have to be 3, for next 3 elements index have to be 6 ...
Should be something like this
<div class="items">
<div class="item" data-index="3"></div>
<div class="item" data-index="3"></div>
<div class="item" data-index="3"></div>
<div class="item" data-index="6"></div>
<div class="item" data-index="6"></div>
<div class="item" data-index="6"></div>
<div class="item" data-index="9"></div>
<div class="item" data-index="9"></div>
<div class="item" data-index="9"></div>
</div>
Anyone have idea how to do it ?
I have this code which add numbers 0, 1, 2, 3, 4, 5...
$('.item').each(function(i) {
$(this).attr('data-index',e)
})

Try this :
$('.item').each(function(i) {
var index = 3 * Math.floor(i / 3) + 3;
$(this).attr('data-index', index);
});

Related

how to display the percentage of progress bar

So I'm trying to display the percentage of each bar on one page, here is the HTML for my progress bars:
<div class="col-md-5">
<p>Progress bar1</p>
<div class="progress progress-striped active">
<div class="progress-bar progress-bar-Success" style="width: 50%;"></div>
</div>
<p>Progress bar2</p>
<div class="progress progress-striped active">
<div class="progress-bar progress-bar-Success" style="width: 20%;"></div>
</div>
<p>Progress bar3</p>
<div class="progress progress-striped active">
<div class="progress-bar progress-bar-Success" style="width: 30%;"></div>
</div>
and this is my js function
$(document).ready(function() {
$(".progress-bar").each(function(index) {
//if(index >=0 && index<=1)
//{
$(this).animate({
width: Math.floor((Math.random() * 100) + 1) + "%"
}, 2500);
// }
})
});
using this i get all bars are automated generated, but i want to display the percentage of each bar, how i can do this ?
This the fiddle
As you using Bootstrap 3, you can add the percentage to the ".progress-bar" div:
Bootstrap docs
$( document ).ready(function() {
$(".progress-bar").each(function (index ) {
//if(index >=0 && index<=1)
//{
var percent = Math.floor((Math.random() * 100) + 1) + "%";
$(this).html(percent);
$(this).animate({width: percent}, 2500);
// }
})
});
Your jsfiddle extended
You can add the percentage text inside the div itself. Check the code below :
<div class="progress progress-striped active">
<div class="progress-bar progress-bar-Success" style="width: 50%;"> 50 </div>
</div>

Check if element has child

I have the following DOM tree (simplified)
<div class=row-0>...</div>
<div class=row-1>
<div class=container>
<div class=panel>...</div>
</div>
</div>
<div class=row-2>...</div>
<div class=row-3>
<div class=container>
<div class=panel>...</div>
<div class=drawer>...</div>
</div>
</div>
<div class=row-4>...</div>
As you can see, all elements have a panel class=panel but not all elements have a drawer class=drawer.
I am iterating through the elements as follows:
const events = Selector('[class^="row-"]');
const eventCount = await events.count;
for (let i = 0; i < eventCount; i++) {
const event = await events.nth(i);
// Here's where I want to check if the event (class=row-x) has a child element class=drawer
const drawer = await Selector(event).child('class["drawer"]')
if (await drawer.exists) {
console.log('Found drawer')
}
}
I can successfully iterate through all the rows, but I cannot detect if a certain event has a drawer. I tried to follow the logic from this answer and also from the docs.
How can I perform this logic?
I suggest you rewrite your test as follows:
Get all "drawer" elements: Selector('div.drawer').
Get all rows that contain the "drawer" elements according to your page hierarchy.
I have created a simple example - please check it out:
index.html:
<html>
<head></head>
<body>
<div class=row-0>Row 0</div>
<div class=row-1>
Row 1
<div class=container>
<div class=panel>...</div>
</div>
</div>
<div class=row-2>Row 2</div>
<div class=row-3>
Row 3
<div class=container>
<div class=panel>...</div>
<div class=drawer>...</div>
</div>
</div>
<div class=row-4>Row 4</div>
<div class=row-5>
Row 5
<div class=container>
<div class=panel>...</div>
<div class=drawer>...</div>
</div>
</div>
</body>
</html>
test.js:
import { Selector } from 'testcafe';
fixture `Fixture`
.page `./index.html`;
test('find rows with "drawer"', async t => {
const drawerElements = Selector('div.drawer').addCustomDOMProperties({
outerHTML: el => el.outerHTML
});
const length = await drawerElements.count;
console.log('Row elements count:', length);
for (let i = 0; i < length; i++) {
console.log('//', i + 1, 'element:');
console.log(await drawerElements.nth(i).parent().parent().outerHTML);
}
});
Command:
testcafe chrome test.js
Result:
Running tests in:
- Chrome 78.0.3904 / Windows 10.0.0
Fixture
Row elements count: 2
// 1 element:
<div class="row-3">
Row 3
<div class="container">
<div class="panel">...</div>
<div class="drawer">...</div>
</div>
</div>
// 2 element:
<div class="row-5">
Row 5
<div class="container">
<div class="panel">...</div>
<div class="drawer">...</div>
</div>
</div>
√ find rows with "drawer"
1 passed (1s)

Find not direct element

Edit: Please take note that the number of parent divs may vary. It may be one or more.
I am trying everything to get the parent <div> of a <div> with class rat that contains a label. So in this case, the outermost <div> must be returned.
<div> --> Should be returned
<div>
<div class="item box1" id="box1">1</div>
<div class="item" id="box2">2</div>
<div class="item" id="box3">3</div>
<div class="item rat" id="box4">4</div>
</div>
<label>Im the original parent</label>
</div>
It can easily be done when I add class attributes for each div and use closest() but for this case there's no unique selector that I can use.
Or we can take it this way: find the closest label of the <div> with class rat using the above example:
$('.rat') -> selector
A recursive approach is the most suitable for your required behavior:
function getParentWithLabel(className) {
function climbRecusively(node) {
const parent = node.parent();
return (parent.find('> label').length ? parent : climbRecusively(parent));
}
return climbRecusively($(`.${className}`));
}
$(function() {
getParentWithLabel('rat').css('background-color', 'grey');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div>
<div class="item box1" id="box1">1</div>
<div class="item" id="box2">2</div>
<div class="item" id="box3">3</div>
<div class="item rat" id="box4">4</div>
</div>
<label>Im the original parent</label>
</div>
I hope this helps.
Maybe it would be easier if you apply your style in your global jQuery, like this :
$('.rat').parent().next();
Try this too
var parentEls = $( ".rat" ).parents();
parentEls.each(function (i, obj) {
if($(obj).find( "> label" ).length){
console.log($(obj).attr('class'));
}
});
Full example : http://jsfiddle.net/harshakj89/ey00czfn/1/

Multiple selection from grid in ionic framework

I want to make a grid of categories images, select multiple categories from them and send their values to controller. I don't know how to achieve this with ionic framework.
Here is my view:
<ion-view cache-view="false">
<div class="bar login-bar bar-header bar-stable">
<h1 class="title ttl-log-bar">Welcome</h1>
</div>
<div class="bar bar-subheader welcome-subhead">
<h2 class="title welc-sub-h2">What do you like to shop for?</h2>
<h5 class="title welc-sub-h5">Pick at least one category</h5>
</div>
<ion-content scroll="true" class="has-header has-subheader">
<div class="row row-cat" style="flex-wrap: wrap;">
<div class="col col-cat col-50" ng-repeat="items in categoryList">
<img ng-src="{{items.image}}" width="100%" />
</div>
</div>
</ion-content>
</ion-view>
Add on img tag ng-click with function passing e.g. ID like this:
<img ng-src="{{items.image}}" ng-click="selectCategory(items.id)" />
Then in controller define this function
$scope.selectedCategory = [];
$scope.selectCategory = function(id){
var index = $scope.selectedCategory.indexOf(id);
if(index === -1){
$scope.selectedCategory.push(id);
}else{
$scope.selectedCategory.splice(index, 1);
}
}
Then you can us selectedCategory array as a collection of selected item's IDs

Bootstrap Responsive Product Grid

I am building a product grid built upon AngularJS data - where there will be images and product details (text)
The text sometimes extends to the 2nd line, causing havoc.
Here is my code:
<div class="row">
<div data-ng-repeat="s in Results">
<div class="col-xs-4">
<a href="#" class="thumbnail">
<div>
<img ng-src="{{s.ProductImage}}" class="img-responsive">
</div>
<div>
{{s.Store}} {{s.Category}} {{s.ProductName}}
</div>
</a>
</div>
<div class="clearfix visible-xs-block"></div>
</div>
</div>
This is what it looks like:
How do I fix it so that <div>s all have the same height?
I tried to look online for solutions, but I think I am 50% there. Please help.
Note: I Don't want to hide content.
This is what I ended up doing for anyone who stumbles on this again in the future.
Javascript
function ResizeToLargestElement(element) {
var maxHeight = -1;
if ($(element).length > 0) {
$(element).each(function () {
maxHeight = maxHeight > $(this).height() ? maxHeight : $(this).height();
});
$(element).each(function () {
$(this).height(maxHeight);
});
}
}
Without AngularJS
For those who aren't using AngularJS, just call ResizeToLargestElement() when data changes or the window is resized using
$(window).resize(function() {
ResizeToLargestElement('.AutoResizeToLargestElement');
});`
With AngularJS
The idea is to call the ResizeToLargestElement() function whenever $scope.Results changes or when the window resizes.
To know when $scope.Results changed is easy, but to know when elements (that are bound to it) finished rendering is not easy. To do that, you need a AngularJS directive.
To know when the window re-sizes, use angular.element($window).on('resize', function () {...});
HTML
<div class="row">
<div data-ng-repeat="s in Results" data-ng-repeat-finished> <!--ADDED Directive-->
<div class="col-xs-4">
<a href="#" class="thumbnail AutoResizeToLargestElement"> <!--ADDED Class-->
<div>
<img ng-src="{{s.ProductImage}}" class="img-responsive">
</div>
<div>
{{s.Store}} {{s.Category}} {{s.ProductName}}
</div>
</a>
</div>
<!--REMOVED clearfix-->
</div>
</div>
MyDirectives.js
angular.module('myApp').directive('ngRepeatFinished', function ($timeout) {
return {
restrict: 'A',
link: function (scope, element, attr) {
if (scope.$last === true) {
$timeout(function () {
scope.$emit('ngRepeatFinished');
});
}
}
}
});
mycontroller.js
$scope.$on('ngRepeatFinished', function (ngRepeatFinishedEvent) {
ResizeToLargestElement(".AutoResizeToLargestElement");
});
angular.element($window).on('resize', function () {
ResizeToLargestElement(".AutoResizeToLargestElement");
});
Note: this requires you to include $window in the AngularJS dependency list.
I.E. angular.module('myApp').controller('....', ['...., '$window', ....]);
If you want to keep the height of each product dynamic, you will need to split the results into columns. And then use ng-if to put the right items in the right column. Every 3rd item will go into the same column. To set them to different columns, just reduce the $index by 1 for each extra column.
<div class="row">
<div class="col-xs-4">
<div ng-repeat="s in Results"> <a href="#" class="thumbnail" ng-if="$index%3==0">
<div>
<img ng-src="{{s.ProductImage}}" class="img-responsive" />
</div>
<div>{{s.Store}} {{s.Category}} {{s.ProductName}}</div>
</a>
<div class="clearfix visible-xs-block"></div>
</div>
</div>
<div class="col-xs-4">
<div ng-repeat="s in Results"> <a href="#" class="thumbnail" ng-if="($index-1)%3==0">
<div>
<img ng-src="{{s.ProductImage}}" class="img-responsive" />
</div>
<div>{{s.Store}} {{s.Category}} {{s.ProductName}}</div>
</a>
<div class="clearfix visible-xs-block"></div>
</div>
</div>
<div class="col-xs-4">
<div ng-repeat="s in Results"> <a href="#" class="thumbnail" ng-if="($index-2)%3==0">
<div>
<img ng-src="{{s.ProductImage}}" class="img-responsive" />
</div>
<div>{{s.Store}} {{s.Category}} {{s.ProductName}}</div>
</a>
<div class="clearfix visible-xs-block"></div>
</div>
</div>
</div>
You can manually restrict the height of the div and use an overflow. Use something like
<div class="col-xs-4" style="height:200px; overflow: auto;">Content</div>
Or, you could always use a responsive table (<table class="table table-responsive">) for your layout.
The best solution for this problem is to add clearfix class to hidden divs for earch size of viewport. for example:
Large size: i want 6 columns (large desktops)
Medium size: i want 4 columns (Desktops)
Tablets: i want 3 coumns
phones: i want 2 columns
so i have the products list:
<?php $count=1; foreach($productList as $product) : ?>
<div class="item col-xs-6 col-sm-4 col-md-3 col-lg-2">
Picture and description
</div><!-- /item -->
<?php if( ($count%2)==0) {?><div class="clearfix visible-xs-block"></div><?php }?>
<?php if( ($count%3)==0) {?><div class="clearfix visible-sm-block"></div><?php }?>
<?php if( ($count%4)==0) {?><div class="clearfix visible-md-block"></div><?php }?>
<?php if( ($count%6)==0) {?><div class="clearfix visible-lg-block"></div><?php }?>
<?php $count++; endforeach?>