how to get current slide index: uib carousel - angular-ui-bootstrap

I would like to get the current slide index onChange and not onClick but I don't know how do do that.
First, I had it with ng-click, like this:
In the .html:
<ul uib-carousel id="myCarousel" active="active" no-wrap="noWrapSlides"
style="background-color: #0a0a0a; height:100%; width:100%; padding: 0">
<li id="mySlides" uib-slide ng-repeat="slide in slides track by slide.id" index="slide.id"
style="background-color: #0a0a0a; height: 100%;width: 100%;">
<img ng-src="{{slide.imageUrl}}" ng-click="setSelectedImage(slide.data)" style="background-color: #0a0a0a; height: 100%;width: 100%; max-height: 640px; max-width: 800px"/>
</li>
</ul>
And in the .js:
$scope.myInterval = 5000;
$scope.noWrapSlides = false;
$scope.active = 0;
var currIndex = 0;
var slides = $scope.slides = [];
$scope.addSlide = function(media,data) {
slides.push({
imageUrl: $scope.urlWsImg+media.mediaId+"/stream/800",
id: currIndex++,
data:data
});
};
$scope.addSlide($scope.currentImage.media,$scope.currentImage);//bootstrap
for(var i=0;i<enrichedImages.length;i++) {
var enrichedImage=enrichedImages[i];
$scope.addSlide(enrichedImage.previewImage,enrichedImage);
}
$scope.setSelectedImage =function(imageUrl){
$scope.currentEnrichedImage=imageUrl;
}
I've tried on put an onchange="setSelectedImage(slide.data)" in #my-carousel, but it doesn't work since the slide is unknown when the change occurs.
I hope someone can help me.

You can't use ngChange because the directive doesn't expose any ngModel
From the ngChange docs
Note, this directive requires ngModel to be present.
But you have the active property that you can $watch
$scope.$watch('active', function(newIndex, oldIndex) {
if (Number.isFinite(newIndex) && newIndex!==oldIndex) {
// invoke your function here
}
});
Here is a forked plunk

It seems that active is holding the current index.
You should be able to just use $scope.active.

Related

Angular Material mat-tabs all have different heights

I wish to have all the tabs have the same height, no matter what contents are inside.
The tabs reside inside a div. Preferably I don't need to set a fixed height for this div, but instead the div should have the height of the mat-tab that has the most stuff.
Haven't found anything really works yet, if someone could help that will be wonderful!
My current code:
HTML:
<div fxLayout="column" style="min-height: 100%; height: 100%">
<mat-tab-group style="height: 100%">
<mat-tab label="1">
<mat-card fxFill class="mat-elevation-z4 about-card">
this mat-card contains the most amount of stuff
</mat-card>
</mat-tab>
<mat-tab label="2">
<mat-card fxFill class="mat-elevation-z4 about-card">
...a bunch of things
</mat-card>
</mat-tab>
<mat-tab label="3">
<mat-card fxFill class="mat-elevation-z4 about-card">
...a bunch of things
</mat-card>
</mat-tab>
</mat-tab-group>
</div>
CSS:
.about-card {
display: flex;
align-items: center;
justify-content: center;
margin: 16px;
padding: 16px;
border-radius: 8px;
}
Edit: Some boilerplate example:
First tab:
Second tab:
See how the heights of the content are different
This is a solution using javascript. You need to get the element with the max height and update the height of mat-tab-body-wrapper container :
ngAfterViewInit() {
const groups = document.querySelectorAll("mat-tab-group");
groups.forEach(group => {
const tabCont = group.querySelectorAll("mat-tab-body");
const wrapper = group.querySelector(".mat-tab-body-wrapper")
const maxHeight = Math.max(...Array.from(tabCont).map(body => body.clientHeight));
wrapper.setAttribute("style", `min-height:${maxHeight}px;`);
});
}
You can transform it using the angular API
Try this.
<mat-tab-group #myTabGroup id="myTabGroup">
ngAfterViewInit() {
this.setTabHeights();
}
#HostListener('window:resize', ['$event'])
handleResize(event: Event) {
this.setTabHeights();
}
setTabHeights() {
const tabCardBody = document
.querySelectorAll('mat-tab-group#setupWarehouseDataTab mat-tab-body');
if (!tabCardBody) return;
const maxHeight = Math.max(...Array.from(tabCardBody)
.map((elm: any) => elm.clientHeight));
tabCardBody.forEach((elm => {
elm.setAttribute('style', `height:${maxHeight}px;`);
});
}

md-datepicker width is too big

I'm stuck to customize size of md-datepicker! I use it in md-input-container but the size after the picker is shown up ,it takes all my screen size.Below is my code:
<md-input-container flex-xs>
<label>Start Date</label>
<md-datepicker ng-model="leave.start_date"></md-datepicker>
</md-input-container>
Do I need to include any original styles of this datepicker? Thank in advance!
Use the function for manipulate width and hide image of calendar as:
var app = angular.module('StarterApp', ['ngMaterial']);
app.controller('AppController', function($scope) {
$scope.initDatepicker = function(){
angular.element(".md-datepicker-button").each(function(){
var el = this;
var ip = angular.element(el).parent().find("input").bind('click', function(e){
angular.element(el).click();
});
angular.element(this).css('visibility', 'hidden');
});
};
});
CSS
This comes from how the date picker is build behind the scene
.inputdemoBasicUsage .md-datepicker-button {
width: 36px;
}
.inputdemoBasicUsage .md-datepicker-input-container {
margin-left: 2px;
}
.md-datepicker-input-container {
display: block;
}
.md-datepicker-input[placeholder] {
color:red;
}
.padding-top-0 {
padding-top: 0px;
}
.padding-bottom-0 {
padding-bottom: 0px;
}
HTML
<div ng-app="StarterApp" ng-controller="AppController" ng-init="initDatepicker();">
<md-content flex class="padding-top-0 padding-bottom-0" layout="row">
<md-datepicker ng-model="user.submissionDate1" md-placeholder="Start date" flex ng-click="ctrl.openCalendarPane($event)"></md-datepicker>
<md-datepicker ng-model="user.submissionDate2" md-placeholder="Due date" flex></md-datepicker>
</md-content>
</div>

Modal box "hidden" behind greyed out area

Im following along with http://multiplethreads.wordpress.com/tag/pagedown/
The example in the link above makes use of twitter bootstrap whereas i make use of zurb foundation.
Basically im trying to get a custom dialog box to insert images from my pagedown editior (sort of like how stackoverflow does it).
Im abale to pull up the modal box (foundation reveal) but it seems to be "behind" something and i cant seem to interact with it. Any ideas?
My code:
js file:
PH.ui.markdown = {
initialize: function () {
var markdownTextArea = $('textarea[data-markdown=true]');
if (markdownTextArea.length == 1) {
markdownTextArea.addClass('wmd-input')
.wrap("<div class='wmd-panel' />")
.before("<div id='wmd-button-bar'></div>")
.after("<div id='wmd-preview' class='wmd-preview'></div>");
var converter = Markdown.getSanitizingConverter();
var editor = new Markdown.Editor(converter);
editor.hooks.set("insertImageDialog", function (callback) {
//setTimeout(function () {
$('#myModal').foundation('reveal', 'open');
// }, 5000);
return true; // tell the editor that we'll take care of getting the image url
});
editor.run();
}
}
};
html:
<div id="myModal" class="reveal-modal">
<h2>Upload Image</h2>
<%= f.file_field :image %>
<button class="btn" id="insert_image_post">Insert Image</button>
<!-- <a class="close-reveal-modal">×</a> -->
</div>
I figured it out.
The wmd-prompt-background had a z-index of 1000:
<div class="wmd-prompt-background" style="position: absolute; top: 0px; z-index: 1000; opacity: 0.5; height: 1085px; left: 0px; width: 100%;"></div>
So i just added:
<style type="text/css">
#myModal {
z-index: 1500;
}
</style>
to my page and it worked.
One way to do it is to position the div of your modal directly under the <body>. This way you make sure that the modal is not part of elements with special z-index

Highlight Nav item when using anchor scrolling

I'm pretty new when it comes to jQuery so I need someone with a little more experience to help me out. I have a Nav with 3 items - Work About Contact
By default I have work selected but I would like it to change the active class to which ever is clicked. I have anchor scrolling working but I would like to have it highlight to the correct nav item when clicked. Also if it is possible when scrolling down the page and getting to the next section for it to change highlight automatically.
This is the jQuery I am using for the anchor scrolling.
<script>$(function() {
var main-nav = $("#main-nav"), pos = main-nav.offset();
$(window).scroll(function() {
if($(this).scrollTop() > (pos.top + 10) && $(this).scrollTop() < 15000 && main-nav.css('position') == 'static') { main-nav.addClass('fixed'); }
else if($(this).scrollTop() <= pos.top && main-nav.hasClass('fixed')){ main-nav.removeClass('fixed'); }
else if($(this).scrollTop() > 15000 && main-nav.hasClass('fixed')){ main-nav.removeClass('fixed'); }
})
});
</script>
<script>$(function() {
$('ul.nav a').bind('click',function(event){
var $anchor = $(this);
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top
}, 1500,'easeInOutExpo');
/*
if you don't want to use the easing effects:
$('html, body').stop().animate({
scrollTop: $($anchor.attr('href')).offset().top
}, 1000);
*/
event.preventDefault();
});
});
</script>
Here is the CSS
#main-nav{
font: bold 12px 'Bitter', serif;
width: 145px;
float: right;
}
#main-nav li{
float: left;
list-style: none;
margin: 10px 2px 0 2px;
color: #c4c5c5;
}
#main-nav li:last-child{
margin-right: 0;
}
#main-nav a{
text-decoration: none;
color: #c4c5c5;
}
#main-nav a:hover{
text-decoration: none;
color: #919292;
}
#main-nav a.active{
color: #919292;
}
Here is the HTML
<div id="main-nav" class="">
<ul class="nav">
<li><a class="active" href="#work">Work</a></li>
<li>/</li>
<li>About</li>
<li>/</li>
<li>Contact</li>
</ul>
</div>
If someone could help me out I would really really appreciate it!
Since you are using the active class to specify which anchor should be highlighted, you just need to make sure that the correct anchor has that class. Fixing that when the nav items are clicked is straightforward, in your $('ul.nav a').bind add:
$('ul.nav a').removeClass('active');
$(this).addClass('active');
Here is a jsbin.
To highlight the nav's as the page is scrolled you would just compare the scrollTop for the page with the offsets of elements in the DOM...similar to your current code in $(window).scroll.

jquery ui sortables connect lists: copy items

I have two lists, I want both of them to be sortable and want to be able to copy (drag) items from list1 to list2 and vice versa.
http://jqueryui.com/demos/sortable/#connect-lists
Is what I want, but the items are moved, not copied.
I did a few experiments with draggables and droppables, but I can't get to to work keeping them sortable. For example: http://jsfiddle.net/tunafish/dvXmf/
OK here is my app; two lists of images, sortable and you can copy over from the connected list.
If an item already exists in the target it's disabled.
Hopefully useful to someone...
JSFiffle here: http://jsfiddle.net/tunafish/VBG5V/
CSS:
.page { width: 410px; padding: 20px; margin: 0 auto; background: darkgray; }
.album { list-style: none; overflow: hidden;
width: 410px; margin: 0; padding: 0; padding-top: 5px;
background: gray;
}
.listing { margin-bottom: 10px; }
.album li { float: left; outline: none;
width: 120px; height: 80px; margin: 0 0 5px 5px; padding: 5px;
background: #222222;
}
li.placeholder { background: lightgray; }
JS:
$("ul, li").disableSelection();
$(".album, .favorites").sortable({
connectWith: ".album, .favorites",
placeholder: "placeholder",
forcePlaceholderSize: true,
revert: 300,
helper: "clone",
stop: uiStop,
receive: uiReceive,
over: uiOver
});
$(".album li").mousedown(mStart);
var iSender, iTarget, iIndex, iId, iSrc, iCopy;
var overCount = 0;
/* everything starts here */
function mStart() {
// remove any remaining .copy classes
$(iSender + " li").removeClass("copy");
// set vars
if ($(this).parent().hasClass("listing")) { iSender = ".listing"; iTarget = ".favorites"; }
else { iSender = ".favorites"; iTarget = ".listing"; }
iIndex = $(this).index();
iId = $(this).attr("id");
iSrc = $(this).find("img").attr("src");
iCopy = $(iTarget + " li img[src*='" + iSrc + "']").length > 0; // boolean, true if there is allready a copy in the target list
// disable target if item is allready in there
if (iCopy) { $(iTarget).css("opacity","0.5").sortable("disable"); }
}
/* when sorting has stopped */
function uiStop(event, ui) {
// enable target
$(iTarget).css("opacity","1.0").sortable("enable");
// reset item vars
iSender = iTarget = iIndex = iId = iSrc = iCopy = undefined;
overCount = 0;
// reinit mousedown, live() did not work to disable
$(".album li").mousedown(mStart);
}
/* rolling over the receiver - over, out, over etc. */
function uiOver(event, ui) {
// only if item in not allready in the target
if (!iCopy) {
// counter for over/out (numbers even/uneven)
overCount++;
// if even [over], clone to original index in sender, show and fadein (sortables hides it)
if (overCount%2) {
if (iIndex == 0) { ui.item.clone().addClass("copy").attr("id", iId).prependTo(iSender).fadeIn("slow"); }
else { ui.item.clone().addClass("copy").attr("id", iId).insertAfter(iSender + " li:eq(" + iIndex + ")").fadeIn("slow"); }
}
// else uneven [out], remove copies
else { $(iSender + " li.copy").remove(); }
}
// else whoooooo
}
/* list transfers, fix ID's here */
function uiReceive(event, ui) {
(iTarget == ".favorites") ? liPrefix = "fli-" : liPrefix = "lli-";
// set ID with index for each matched element
$(iTarget + " li").each(function(index) {
$(this).attr("id", liPrefix + (index + 1)); // id's start from 1
});
}
HTML:
<div class="page">
<div class="container">
<h2>Photo Album</h2>
<ul class="listing album">
<li id="li-1"><img src="tn/001.jpg" /></li>
<li id="li-2"><img src="tn/002.jpg" /></li>
<li id="li-3"><img src="tn/003.jpg" /></li>
<li id="li-4"><img src="tn/004.jpg" /></li>
<li id="li-5"><img src="tn/005.jpg" /></li>
</ul>
</div>
<div style="clear:both;"></div>
<div class="container">
<h2>Favorites</h2>
<ul class="favorites album">
<li id="fli-1"><img src="tn/001.jpg" /></li>
<li id="fli-2"><img src="tn/002.jpg" /></li>
<li id="fli-3"><img src="tn/010.jpg" /></li>
</ul>
</div>
</div>
I have to say that FFish's answer to this has been incredibly helpful to me.
I'd make one suggestion; if the lists are being constantly changed the mousedown event seem to be called numerous times because of the re-registering of the event on all the child objects. It might be a bit of a kludge, but I've added an unbind first to ensure the mousedown event is only called once.
$(".album li").mousedown(mStart);
to
$(".album li").unbind('mousedown', mStart).mousedown(mStart);

Resources