Vue JS transition toggle based of class binded - ease down and up - vue.js

Using Vue JS i am trying to transition the read more/read less by dropping/closing by transitioning the max-height properties with ease.
This itemBio is sitting in a bootstrap vue modal (if this is relevant).
If the readMore data is true then the readMore class is binded to the itemBio class div. This then activates the max-height property to 100%.
Though doesn't seem to be working at all. Just instantly shows/closes the div.
this is what i have so far:
.itemBio {
max-height: 51px;
overflow: hidden;
transition: max-height 5s ease;
&.readMore {
max-height: 100%;
overflow: auto;
transition: max-height 5s ease;
&::-webkit-scrollbar {
display: none;
}
}
}
<div class="itemBio font-14 text-grey69 w-100"
:class="{'readMore':readMore}"
style="line-height: 17px;"
:ref="'countLines' + menuItem.uuid">
{{ menuItem.description }}
<button #click="$refs.allergensModal.show()"
class="mt-10 w-100 text-left"
v-if="dietaryTrue !== 0"
>
<span class="allergen green"
v-if="menuItem.dietary.vegetarian">
V
</span>
<span class="allergen aqua"
v-if="menuItem.dietary.vegan">
VG
</span>
<span class="allergen gold"
v-if="menuItem.dietary.gluten_free">
GF
</span>
<span class="allergen pink"
v-if="menuItem.dietary.halal">
HA
</span>
<span class="allergen yellow"
v-if="menuItem.dietary.soy_free">
SF
</span>
<span class="allergen brown"
v-if="menuItem.dietary.nut_free">
NF
</span>
<span class="allergen blue"
v-if="menuItem.dietary.dairy_free">
DF
</span>
</button>
</div>
<button class="text-teal font-black font-12" #click="showItemBio()" v-if="lines > 2">
<span v-if="!readMore">Read More</spa`enter code here`n>
<span v-if="readMore">Read Less</span>
</button>
Typescript:
readMore: boolean = false;
showItemBio() {
this.readMore = !this.readMore;
}

I have made one sample example. Check this once. This may help.(you mention 100% in max-height and in starting max-height you mentioned 51px thats might be the problem for not transitioning. Maintain both in px or %)
<template>
<div id="app">
<div class="paragraph" :class="{showmore:checkStatus}">
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).
</p>
</div>
<button #click="changeData">{{ readStatus }}</button>
</div>
</template>
<script>
export default {
name: 'App',
data:function(){
return {
readStatus:'readmore',
checkStatus:false
}
},
methods:{
changeData:function(){
if(this.readStatus=='readmore'){
this.readStatus='readless';
this.checkStatus=true;
}else{
this.readStatus='readmore';
this.checkStatus=false;
}
}
}
}
</script>
<style scoped>
.paragraph {
max-height: 100px;
overflow: hidden;
transition: max-height 2s;
}
.paragraph p{
color: black;
}
.showmore{
max-height: 500px;
overflow: auto;
}
</style>

Related

v-for with varaible number of content blocks

Is there a way to have variable amount of content blocks inside a v-for loop? Say one of the instances has 1 content paragraph and an other needs 3 content paragraphs? Would you have to create a nested loop inside the outer loop?
https://codepen.io/mDDDD/pen/dyWRqJW
<div id='timeline' class="timeline container">
<div class="timeline__main">
<div
class="timeline__main--inner"
v-for="year in timelines"
:key="year.id"
ref="timelines"
>
<div class="timeline-title">
<h3 class="title-3">{{ year.year }}</h3>
</div>
<div class="timeline-content">
**(one of the instances this needed 3 P tags with class history content?)**
<p class="history-description">
{{ year.content }}
</p>
const Timeline = {
data() {
return {
timelines: [
{ id: 2020, year: '2020', content: `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. `},
{ id: 2019, year: '2019', content: `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. ` },
],
};
},
};
Vue.createApp(Timeline).mount("#timeline");
</div>
</div>
</div>
</div>
Two adjustments: (1) to the data, representing N paragraphs per year, and (2) the important one in the markup, nesting a v-for to iterate the nested array.
var app = new Vue({
el: '#app',
data() {
return {
timelines: [{
id: 2020,
year: '2020',
content: [`The first paragraph in 2020`, `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. `]
},
{
id: 2019,
year: '2019',
content: [`The first paragraph in 2019`, `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. `]
},
],
};
},
})
.timeline__main--inner {
display: flex;
margin-bottom: 75px;
}
.timeline__main {
width: 100%;
max-width: 785px;
margin: 0 auto;
}
.timeline-title {
display: flex;
align-items: center;
padding-right: 65px;
border-right: 1px solid grey;
h3 {
color: green;
font-size: 60px;
}
}
.timeline-content {
padding: 15px 54px 15px 62px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div id='timeline' class="timeline container">
<div class="timeline__main">
<div class="timeline__main--inner" v-for="year in timelines" :key="year.id" ref="timelines">
<div class="timeline-title">
<h3 class="title-3">{{ year.year }}</h3>
</div>
<div class="timeline-content">
<p class="history-description" v-for="(p,i) in year.content" :key="i">
{{ p }}
</p>
</div>
</div>
</div>
</div>
</div>

How to pass imageUrl as props?

Here is my component. It takes a props imageUrl which is String referring either an image from a URL or a reference to a local asset from the assets folder
<template>
<div class="flex" style="height: 155px;align-items: center">
<div class="avatar" style="height: 130px;width: 130px">
<img :src="require(`imageUrl`)" height="130" width="130" style="border-radius: 50%"/>
</div>
<div class="flex flex-column" style="margin-left: 31px">
<div class="flex" style="font-weight: bold">
{{fullName}}
</div>
<div class="flex" style="">
{{title}}
</div>
<div style="height: 20px"></div>
<div class="flex" style="text-align: start">
{{content}}
</div>
</div>
</div>
</template>
<script>
export default {
name: "ReviewTile",
props: {
imageUrl: String,
fullName: String,
title: String,
content: String
}
}
</script>
<style scoped>
</style>
I use it like this:
<ReviewTile
image-url="../assets/Eugene.png"
full-name="Eugene B.
"
title="UI/UX Designer."
content=" Christabel is one of the business world’s truly great deal makers and strategists, easily on par with
the best of the strategy consultants and designers I have worked with at SOS-HGIC and Kleio. She is also
a world-class human being."
></ReviewTile>
<div style="background-color: #b7b7b7;height: 1px; margin: 33px 0px"></div>
<ReviewTile
image-url="../assets/headshot_black1.png"
full-name="Gilliam D."
title="Web designer/Developer"
content="Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo."
></ReviewTile>
But images are not loading.
There is a strange JS bug that breaks proper image loading (sry, I forgot what it was, but I found the solution on stackoverflow a while ago).
What helps is breaking the image request up like this:
:src="require('#/assets/' + imageName + '')"
So you only have your image name in the prop and load it without the curly brackets. Now you also don't have to worry about the correct path. The # will find the correct folder.
If anyone can explain the technicalities of this better or finds the other thread with the solution, please feel free to expand on my answer.
Edit: First part of the explanation: Webpack can't work with only a variable as path, because then it would have to go over potentially thousands of files. So you have to have the #/assets/ part as text. Explained more nicely here: Vue.js dynamic image src with webpack require() not working
Couldn't find yet why the curly brackets don't work.
If all your images are in the same folder your can just pass the file name as props:
<ReviewTile
image-url="Eugene.png"
...
></ReviewTile>
<ReviewTile
image-url="headshot_black1.png"
...
></ReviewTile>
Then in the ReviewTitle component, require the imageUrl with the assets path:
<div class="avatar">
<img :src="require(`../assets/${imageUrl}`)" />
</div>
Note:
If all the images have the same extension .png you can even just write the file name like image-url="Eugene" and in the component: <img :src="require(`../assets/${imageUrl}.png`)" />
if you are sending the path of the image in the url, then you can use the props directly,
but make sure you are providing the right path to the image.
<img :src="imageUrl" height="130" width="130" style="border-radius: 50%"/>
also change your prop name in the other component
// Wrong
<ReviewTile
image-url="../assets/Eugene.png"
full-name="Eugene B.
// correct one would be something like this
<ReviewTile
:imageUrl="../assets/Eugene.png"
full-name="Eugene B.
For those using Nuxt.js for the Vue apps - there is simple solution using static folder instead of assets.
The key difference between these two folders is that static is not compiled by Webpack - therefore you are free to use variables as you please.
See the docs:
https://nuxtjs.org/docs/2.x/directory-structure/static

How can we show multiple items with Bootstrap-Vue Carousel?

I think boostrap-vue carousel not so detailed. For this reason i can't reach to nice solution.
I wanna just show 3 items (like in image) in my app and i didnt find the solution and i searched other package and there was no solution for me.
All i want to do like this;
data() {
return {
slide: 0,
sliding: null
};
},
methods: {
onSlideStart(slide) {
this.sliding = true;
},
onSlideEnd(slide) {
this.sliding = false;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div>
<b-carousel id="carousel-1" v-model="slide" :interval="0" controls indicators background="white" img-width="650" img-height="480" #sliding-start="onSlideStart" #sliding-end="onSlideEnd">
<b-carousel-slide caption="First slide" text="Nulla vitae elit libero, a pharetra augue mollis interdum." img-src="https://picsum.photos/1024/480/?image=52"></b-carousel-slide>
<b-carousel-slide img-src="https://picsum.photos/1024/480/?image=54">
<h1>Hello world!</h1>
</b-carousel-slide>
<b-carousel-slide img-src="https://picsum.photos/1024/480/?image=58"></b-carousel-slide>
<b-carousel-slide>
<img slot="img" class="d-block img-fluid w-100" width="1024" height="480" src="https://picsum.photos/1024/480/?image=55" alt="image slot">
</b-carousel-slide>
</b-carousel>
<p class="mt-4">
Slide #: {{ slide }}<br> Sliding: {{ sliding }}
</p>
</div>
If you have any other library suggestion i would appreciate.
Thanks for help.
BootstrapVue <b-carousel> is designed to only show a single slide at a time (as is the standard bootstrap V4.x carousel component). There are never more than 2 slides visible at once (during the slide or fade transition, all other slides are hidden. CSS transforms are used to make the appearance of the slides moving)
You would need to either find a 3rd party component that supports multiple slides showing, or generate your own custom component.
I'm not familiar with this specific component, but this is from its documentation:
<!-- Slide with blank fluid image to maintain slide aspect ratio -->
<b-carousel-slide caption="Blank Image" img-blank img-alt="Blank image">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse eros felis, tincidunt
a tincidunt eget, convallis vel est. Ut pellentesque ut lacus vel interdum.
</p>
</b-carousel-slide>
I would try using a blank image as the default and inserting whatever other images/content you want as children of the slide:
<!-- Slide with blank fluid image to maintain slide aspect ratio -->
<b-carousel-slide caption="Blank Image" img-blank img-alt="Blank image">
<img class="my-img" src="img1.jpg"/>
<img class="my-img" src="img2.jpg"/>
<img class="my-img" src="img3.jpg"/>
</b-carousel-slide>
And use absolute positioning or flexbox to display them the way you want.
I did the same thing using b-card-group. Because b-carousel does not support showing multiple items.
In template area
<div>
<!-- carousel area -->
<b-card-group deck class="mb-0">
<b-card v-for="(item,index) in currentPageCards" :key="index" class="mr-0">
<!-- card content -->
</b-card>
</b-card-group>
<!-- pagination area -->
<div class="pagination" v-if="cards.length>cardsPerPage">
<div class="index" v-for="i in pageCount" :key="i" #click="next(i)" :class={active:currentPage(i)}></div>
</div>
</div>
In script area
data() {
return {
cards: [{
//Data in the card as objects
},{},{},{},{}],
paginatedCards:[],
pageCount:0,
cardsPerPage:4,
currentPageIndex:0
}
},
computed: {
currentPageCards(){
this.createPages();
return this.paginatedCards[this.currentPageIndex];
}
},
methods:{
currentPage(i){
return i-1===this.currentPageIndex;
},
createPages() {
let cardsLength = this.cards.length;
let fullPagesCount = Math.floor(cardsLength/this.cardsPerPage);
if(cardsLength>this.cardsPerPage) {
this.pageCount = 0;
for (let i = 0; i < fullPagesCount * this.cardsPerPage; i += this.cardsPerPage) {
this.paginatedCards[this.pageCount] = this.cards.slice(i,i + this.cardsPerPage);
this.pageCount++;
}
this.paginatedCards[this.pageCount] = this.cards.slice(cardsLength-this.cardsPerPage,cardsLength);
this.pageCount = this.pageCount+1;
} else {
this.paginatedCards[0] = this.cards;
}
},
next(i){
this.currentPageIndex=i-1;
}
}
In style area
.pagination{
display:flex;
align-items: center;
justify-content: center;
padding:10px;
}
.index{
margin-left:10px;
width:10px;
height:10px;
background:#000000
}
.active{
width:15px;
height:15px;
}
It shows like as below
Try this one. Thank you!

Bootstrap 3 Column Alignment

MY (COMMON) PROBLEM:
I am struggling with what I feel is an old or common problem with BootStrap 3 column alignment, but I am not sure how to articulate myself enough to find specific answers online via googling them, thus why I am posting this here.
Here is an example of my layout:
Depiction of Layout:
If you look at the first column, second row on the lower left you'll see a VERY long title, that now creates a bad alignment with the second column paragraph on the lower right and it looks unprofessional/unintentional.
WHAT I TRIED:
I've tried making a specific min-height to the h4 tags, but, of course the layout will make the layout change as the viewport changes.
I've tried specific CSS properties (like center-fix or flex???) and that only makes the element centered within the parent div, it STILL looks off and thus unprofessional.
MY CODE:
<style type="text/css">
.feature{
margin-bottom: 6%;
padding-left: 40px;
padding-right: 40px;
}
.bottom_icon_padding {
margin-bottom: 27px;
}
#other_features h4 {
text-align: center;
min-height:10%;
}
.field-item img {
padding: 0px;
}
</style>
<div class="col-md-offset-1 col-md-10">
<h4 style="color:#666;line-height: 2.3rem;">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</h4>
<hr>
</div>
<div class="col-sm-12" id="other_features">
<div class="row">
<div class="col-md-offset-1 col-md-5 feature" ><img alt="Unmeeting Logo" src="/sites/default/files/unmeeting_logo.png" />
<h4 class="bottom_icon_padding" >Unmeeting RFAs</h4>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s.</p>
<p>Learn more</p>
</div>
<div class="col-md-5 feature" ><img alt="Synergy Logo" src="/sites/default/files/synergy_logo.png" />
<h4 class="bottom_icon_padding" >Synergy RFAs</h4>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s</p>
<p>Learn more</p>
</div>
</div>
<div class="row" >
<div class="col-md-offset-1 col-md-5 feature" ><img alt="Certificate Variant With Image" src="/sites/default/files/030-certificate-variant-with-image.png" />
<h4 class="bottom_icon_padding" >CTSA Program Collaborative Innovation Awards: Administrative Supplements</h4>
<p>These supplements allow investigators from two or more CTSA Program hubs to form collaborations to implement, assess, and/or disseminate discoveries in methods, approaches, education and training in clinical and translational science.</p>
<p>View site</p>
</div>
<div class="col-md-5 feature" ><img alt="Premium Badge" src="/sites/default/files/035-premium-badge.png" />
<h4 class="bottom_icon_padding" >SmartIRB</h4>
<p>SMART IRB is a platform designed to ease common challenges associated with initiating multisite research and to provide a roadmap for institutions to implement the NIH Single IRB Review policy.</p>
<p>View site</p>
</div>
</div>
</div>
MY QUESTION:
This is for a client that has ALOT of restrictions on layout so I can't just move anything around, can anyone make any suggestions so the bottom two paragraph sections align no matter what the viewport size is?
There could be one solution to set min-height:40px if you are sure of the content in your website.
Another solution could be that you modify your structure in a way that your Images come in one row and your describing text go to next row. Can post details if it suits you
.feature {
margin-bottom: 6%;
padding-left: 40px;
padding-right: 40px;
}
.bottom_icon_padding {
margin-bottom: 27px;
}
#other_features h4 {
text-align: center;
min-height: 40px;
}
}
.field-item img {
padding: 0px;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<div class="container">
<div class="col-md-offset-1 col-md-10">
<h4 style="color:#666;line-height: 2.3rem;">Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It
has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop
publishing software like Aldus PageMaker including versions of Lorem Ipsum.</h4>
<hr>
</div>
<div class="col-sm-12" id="other_features">
<div class="row">
<div class="col-md-offset-1 col-md-5 feature"><img alt="Unmeeting Logo" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSqrfVof7CYYRtsdCu1VD4AWoPB2gs25PP5hQAuhOwhZngrOhsS" />
<h4 class="bottom_icon_padding">Unmeeting RFAs</h4>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s.</p>
<p>Learn more</p>
</div>
<div class="col-md-5 feature"><img alt="Synergy Logo" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSqrfVof7CYYRtsdCu1VD4AWoPB2gs25PP5hQAuhOwhZngrOhsS" />
<h4 class="bottom_icon_padding">Synergy RFAs</h4>
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s</p>
<p>Learn more</p>
</div>
</div>
<div class="row">
<div class="col-md-offset-1 col-md-5 feature"><img alt="Certificate Variant With Image" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSqrfVof7CYYRtsdCu1VD4AWoPB2gs25PP5hQAuhOwhZngrOhsS" />
<h4 class="bottom_icon_padding">CTSA Program Collaborative Innovation Awards: Administrative Supplements</h4>
<p>These supplements allow investigators from two or more CTSA Program hubs to form collaborations to implement, assess, and/or disseminate discoveries in methods, approaches, education and training in clinical and translational science.</p>
<p>View site</p>
</div>
<div class="col-md-5 feature"><img alt="Premium Badge" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSqrfVof7CYYRtsdCu1VD4AWoPB2gs25PP5hQAuhOwhZngrOhsS" />
<h4 class="bottom_icon_padding">SmartIRB</h4>
<p>SMART IRB is a platform designed to ease common challenges associated with initiating multisite research and to provide a roadmap for institutions to implement the NIH Single IRB Review policy.</p>
<p>View site</p>
</div>
</div>
</div>
</div>

how to disable single tab in dojo tabcontainer

i want to disable single tab in tabcontainer of dojo .
Here's my workaround for this problem:
dojo.style(dijit.byId("tabID").controlButton.domNode,{display:"none"});
and:
dojo.style(dijit.byId("tabID").controlButton.domNode,{display:"inline-block"});
For some reason, altering the disabled property, or calling setDisabled does nothing for me.
You can't do it directly since this is not a feature of the DOJO tab container. There has been a bug against DOJO, open for about 3 years, to add the feature: http://bugs.dojotoolkit.org/ticket/5601
That defect also has a potential workaround in it.
dijit.byId('tab').controlButton.domNode.disabled = true
I answered this question in another thread. Basically it involved getting jQuery involved. Works great for me. I have all the tabs created statically (as opposed to programatically) and I'm able to manipulate whether they are shown or hidden with the help on jQuery. All the code any everything is in my post here:
How do I dynamically show and hide an entire TabContainer using DOJO?
You can override its default css to make the tabbar invisible.
dojo.attr(dijit.byId('tab'), "disabled", true);
dijit.byId('tab').onClick = function () { };
You can disable tabs by setting the disabled property of the pane:
Source: https://dojotoolkit.org/reference-guide/1.10/dojo/dom-style.html
pane.set("disabled", true);
Example:
<div data-dojo-type="dijit/layout/TabContainer" style="width: width: 350px; height: 200px">
<div data-dojo-type="dijit/layout/ContentPane" title="My first tab" data- dojo-props="selected:true">
Lorem ipsum and all around...
</div>
<div data-dojo-type="dijit/layout/ContentPane" id="second" title="My second tab">
Lorem ipsum and all around - second...
</div>
<div data-dojo-type="dijit/layout/ContentPane" title="My last tab" data- dojo-props="closable:true">
Lorem ipsum and all around - last...
</div>
</div>
<script type="dojo/require">
registry: "dijit/registry"
</script>
<button type=button onclick="registry.byId('second').set('disabled', !registry.byId('second').get('disabled'));">
toggle tab #2 disabled
</button>
Only problem here is that it's not visible to the user they can't click on it.
You can these additional CSS selectors:
.dijitTab.dijitDisabled {
cursor: not-allowed !important;
}
.dijitTab.dijitDisabled > .tabLabel{
cursor: not-allowed !important;
}