I am trying to create 3 tooltips in a page, Its not working , only one tooltip should be open on click anyother tooltip should be closed.
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('TooltipDemoCtrl', function ($scope, $sce) {
$scope.tooltip = {
1: false,
2: false,
3: false
};
$scope.tooltipCloseActive = function(activeTooltip) {
console.log($scope.tooltip);
_.set($scope.tooltip, activeTooltip, true);
_.forOwn($scope.tooltip, function(value, key) {
console.log(value+'*************'+key);
if(activeTooltip !== key && value === true){
console.log('#'+key);
_.set($scope.tooltip, key, false);
$scope.triggerClickOnTooltip(key);
console.log(key);
}
});
};
$scope.triggerClickOnTooltip = function(id) {
setTimeout( function(){
angular.element(document.querySelectorAll('#'+id)).trigger('click');
}, 100);
};
});
HTML:
<div class="col-xs-10 col-sm-4">
<p id="1" tooltip-trigger="click"
uib-tooltip="I am a tooltip 1." ng-click="tooltipCloseActive('1');">
<span>tooltip 1:</span>
</p>
<br>
<p id="2" tooltip-trigger="click"
uib-tooltip="I am a tooltip 2." ng-click="tooltipCloseActive('2')">
<span >tooltip 2:</span>
</p>
<br>
<p id="3" tooltip-trigger="click"
uib-tooltip="I am a tooltip 3." ng-click="tooltipCloseActive('3')">
<span>tooltip 3:</span>
</p>
<br>
</div>
I have written code for multiple ui tooltips and want to close other tooltips when one of the tooltip is clicked.
It is going into infinite loop so when I am triggering click .
Just want to know how to make it work :
Possible Solution :
1) Differentiating the user click and trigger click :
I was not able to differentiate (I know how we can do in jquery but not in angular)
2) Use tooltip flags ( which I did it didn't work)
3) Upgrading ui bootstrap and use outsideClick (Which I cant afford doing in our application right now)
Is there any way I can solve this mystery of enable only one tooltip at a time.
Any help would be greatly appreciated.
PLUNKER : http://plnkr.co/edit/mjqGa26auDSY2G8ThAk4?p=preview
I think I was over thinking on trigger :
I have used is-open with wrong format due to which I was not able to get the
Working plunker using mutliple tooltips and enabling using tooltip-is-open http://plnkr.co/edit/gKqdoA3qK74XD1r9b5PR?p=info
HTML:
Tooltip Text
<br/> Toggle value: {{ tooltip.isTTOpen }}
</div>
<br/>
<br/>
<br/>
<br/>
<span tooltip-template="'myTooltipTemplate.html'" tooltip-trigger="none" tooltip-is-open="tooltip.isTTOpen2" tooltip-placement="top" ng-click="closeTooltip('isTTOpen2')">Tooltip Text</span>
<br/> Toggle value: {{ tooltip.isTTOpen2 }}
<br/>
<br/>
<br/>
<br/>
<span tooltip-template="'myTooltipTemplate.html'" tooltip-trigger="none" tooltip-is-open="tooltip.isTTOpen3" tooltip-placement="top" ng-click="closeTooltip('isTTOpen3')">Tooltip Text</span>
<br/> Toggle value: {{ tooltip.isTTOpen3 }}
JS:
$scope.tooltip = {
isTTOpen: false,
isTTOpen2: false,
isTTOpen3: false
};
$scope.closeTooltip = function(tooltip) {
console.log(tooltip);
for (var key in $scope.tooltip) {
if ($scope.tooltip.hasOwnProperty(key)) {
console.log(key + " -> " + $scope.tooltip[key]);
if (tooltip === key) {
$scope.tooltip[key] = true;
} else {
$scope.tooltip[key] = false;
}
}
}
};
Related
I've this quiz app, True/False statements in one question and T and F button against each statement. When I select the options and click on next/back button, active class gets removed from the previous one. As I'm a beginner, I can't think what I'm doing wrong. any help please?
Demo: https://stackblitz.com/edit/angular-ivy-4yczgp
<div class="qitem qclose"
[ngClass]="{'qclose-active': selectAnswer[j]?.dirty && (selectAnswer[j].select == 'false')}"
(click)="changeFalse(j , item)">
<i class="qitembox qclose-icon"></i>
</div>
<div class="qitem qtick"
[ngClass]="{'qtick-active': selectAnswer[j]?.dirty && (selectAnswer[j].select == 'true')}"
(click)="changeTrue(j , item)">
<i class="qitembox qtick-icon"></i>
</div>
You need to assign that object to model not as generic Demo
your assigns functions
changeFalse(i, option) {
console.log(option.id);
option.selectAnswer = { select: 'false', dirty: 'true' };
}
changeTrue(i, option) {
console.log(option.id);
option.selectAnswer= { select: 'true', dirty: 'true' };
}
your html
<div class="ccq">
<div class="qitem qclose" [ngClass]="{'qclose-active': item.selectAnswer?.dirty && (item.selectAnswer?.select == 'false')}" (click)="changeFalse(j , item)">
<i class="qitembox qclose-icon">F</i>
</div>
<div class="qitem qtick" [ngClass]="{'qtick-active': item.selectAnswer?.dirty && (item.selectAnswer?.select == 'true')}"(click)="changeTrue(j , item)">
<i class="qitembox qtick-icon">T</i>
</div>
</div>
Im trying to implement dropdown menu in oracle JET but if I click on the menu link it doesn't work :( What am I doing wrong?
html:
<div id='menubutton-container'>
<oj-menu id="myMenu" slot="menu" style="display:none" on-oj-action="[[menuItemAction]]">
<oj-option id="ac" value="Additional Compensation" >
<span class="demo-icon-font demo-fire-icon-24" slot="startIcon"></span>
<a id="1ds" href="#2"
data-bind="click: menuItemAction">MyLink</a>
</oj-menu>
</oj-menu-button>
</div>
vieModel js:
self.selectedMenuItem = ko.observable("(None selected yet)");
self.menuItemAction = function( data, event )
{
this.selectedMenuItem(event.currentTarget.id);
return true;
};
Bootstrap.whenDocumentReady().then(
function()
{
ko.applyBindings(new EmployeesViewModel, document.getElementById('menubutton-container'));
}
);
First there is no closing tag for oj-option and starting tag for oj-menu-button.
The currentTarget.id it will refer to oj-menu.
below html and js works fine
<div id='menubutton-container'>
<oj-menu-button>
<oj-menu id="myMenu" slot="menu" style="display:none" on-oj-action="[[menuItemAction]]">
<oj-option id="ac" value="Additional Compensation" >
<span class="demo-icon-font demo-fire-icon-24" slot="startIcon">MyLink</span>
</oj-option>
</oj-menu>
</oj-menu-button>
self.selectedMenuItem = ko.observable("(None selected yet)");
self.menuItemAction = function (event)
{
console.log(event.currentTarget);
console.log(event.currentTarget.id);
console.log(event.target.value);
self.selectedMenuItem(event.target.value);
return true;
};
I'm using Vue v2
I'm trying to change only the properties of the selected element. See, when the response is marked after the click, it should change to a red color with a text that says 'Unmark'. And vice versa: if the button is clicked again (which now would say 'Unmark'), it should change to a green color and the text would be 'Mark'. Alas, it works.... Nevertheless, my code applies the change to every element inside the v-for; I only want that to happen to the selected element.
I've thought about using a Component to check if somethings changes, but first I'd like to see if there's a solutions for this. ANy help will be appreciated
Here's my code:
<div class="search-results">
<div class="activity-box-w" v-for="user in users">
<div class="box">
<div class="avatar" :style="{ 'background-image': 'url(' + user.customer.profile_picture + ')' }">
</div>
<div class="info">
<div class="role">
#{{ '#' + user.username }}
</div>
<div>
<div>
<p class="title">#{{ user.customer.name }}
#{{user.customer.lastname}}
</p>
</div>
</div>
</div>
<div class="time">
<input type="button" class="btn btn-sm btn-primary" v-on:click.prevent="markUser(user)" v-model="text"
v-bind:class="[{'green-border':notMarked}, {'red-border':marked}]" v-cloak v-if="!action"
:disabled="action"></input>
</div>
</div>
</div>
Now for the script:
new Vue({
el: '#engage-panel',
data: {
users: [],
mark: {'id' : '', 'marks' : ''},
text: 'Mark', //Migth change to Unmark later on
action: false,
marked: null,
notMarked: null,
},
methods:
{
markUser: function(user){
this.mark.id = user.id;
this.action= true;
Vue.http.headers.common['X-CSRF-TOKEN'] = $('meta[name="csrf-token"]').attr('content');
this.$http.put('/mark/user', this.mark).then(response => {
if(response.body === "marked")
{
this.mark.marks="true";
this.text = 'Unmark';
this.marked= true;
this.notMarked= false;
this.action= false;
}else{
this.mark.marks="false";
this.text = 'Mark';
this.marked= false;
this.notMarked= true;
this.action= false;
}
}).catch(e => {
this.action= false;
});
}
}
You can use $event.target on click if you just need to toggle css class.
fiddle here
But it's true that it's easier if a user has a status like marked = true/false for example, you just need to bind class like :
<input :class="{ 'green-border': user.marked, 'red-border': !user.marked }">
The issue my code applies the change to every element you met is caused by every user in v-for="user in users" uses one same object to indicates it is marked or not.
If your users data has one property like status to save current status (like unmark, mark etc), it is very simple, just change to next status when click mark button.
If your users data doesn't have that property, you need to create one dictionary, then save the users already clicked as key, the status for the user will be the value.
Below is one demo:
app = new Vue({
el: "#app",
data: {
users1: [{'name':'abc', 'status':'none'},
{'name':'xyz', 'status':'none'}],
users2: [{'name':'abc'}, {'name':'xyz'}],
selectedUsers: {}
},
methods: {
getNextStatusBaseOnRoute: function (status) {
if(status ==='marked') return 'marked'
let routes = {'none':'unmark', 'unmark':'marked'}
return routes[status]
},
markUser1: function (item) {
item.status = this.getNextStatusBaseOnRoute(item.status)
},
markUser2: function (item) {
let status = item.name in this.selectedUsers ? this.selectedUsers[item.name] : 'none'
// remember to use vue.$set when adding new property to one object
this.$set(this.selectedUsers, item.name, this.getNextStatusBaseOnRoute(status))
}
}
})
.marked {
background-color:green;
}
.unmark {
background-color:yellow;
}
<script src="https://unpkg.com/vue#2.5.16/dist/vue.js"></script>
<div id="app">
<h2>Case 1: </h2>
<div v-for="(item, index1) in users1" :key="'1'+index1">
<span>{{item.name}}:</span><span :class="[item.status]">{{item.status}}</span><button #click="markUser1(item)">Mark</button>
</div>
<h2>Case 2: </h2>
<div v-for="(item, index2) in users2" :key="'2'+index2">
<span>{{item.name}}:</span><span :class="[item.name in selectedUsers ? selectedUsers[item.name] : 'none']">{{item.name in selectedUsers ? selectedUsers[item.name] : 'none'}}</span><button #click="markUser2(item)">Mark</button>
</div>
</div>
For Vue3, you can also store the index of the selected element
<ul role="list" class="">
<li class="relative" v-for="(image, index) of images" :class="selectedImage == index? 'border-indigo-500 border-2': 'border-transparent'" >
<div #click="selectedImage = index" class="">
<img :src="image" alt="" class="object-cover pointer-events-none group-hover:opacity-75">
</div>
</li>
</ul>
Has anyone used foundation's slider component with React? I'm trying to capture and set the state based off the slider value, but I'm having serious issues. I'm looking for an approach that does not utilize jQuery.
When the input type is set to 'hidden' I can't seem to grab any data from the slider. When I change that to 'number', then an input box appears and I am able to grab data from that. The final design does not include an input box, so I need to maintain the 'hidden' attribute.
Can anyone seem to see a flaw in my code? At best, I get 'undefined' when trying to setState, but again, that's when I am showing an input box.
This is the code I have so far...
export class _DailyCheck extends Component {
state = {
levels: {
sleep: 0,
energy: 0,
stress: 0
},
show: true
}
_renderDaily () {
const { levels: { sleep, energy, stress } } = this.state
return (
<div>
<div className='content'>
<p className='headline-1 text-left'>
How is your day
going so far?
</p>
<div className='grid-x grid-padding-x'>
<fieldset className='small-12 large-12 cell'>
<label className='bold-body'>
Sleep Quality
<div
className='slider slider-margin'
data-slider
data-initial-start='3'
data-end='6'
>
<span
className='slider-handle'
data-slider-handle
tabIndex='1'
aria-controls='sleep'
>
</span>
<span
className='slider-fill'
data-slider-fill
>
</span>
<input
type='range'
id='sleep'
value={sleep}
onClick={(e) => this._handleDailyChange(e) }
/>
</div>
</label>
</fieldset>
</div>
</div>
</div>
)
}
_handleDailyChange (event) {
const levels = { ...this.state.levels }
levels[event.target.name] = levels[event.target.value]
this.setState({ levels })
}
if we create two or three comment with multiple replies to them the "helpful" link is causing problem when clicked it perform ng-click operation on the index with same number thus showing all the text with same index. how to resolve this nesting so that when a link is clicked only the respective text is shown
http://plnkr.co/edit/XS4Nro3sdIWMnopdgDYG?p=preview
the ng-click and ng-show operation are working through myDiscuss controller
var app = angular.module("myDiscuss", []);
app.controller("TabController", function($scope) {
$scope.subTab = null;
$scope.subLike=null;
$scope.selectSubLike = function (setTab) {
$scope.subLike=setTab;
}
$scope.selectSubTab = function(setTab){
$scope.subTab = setTab;
};
$scope.isSelectedSub = function(checkTab){
return $scope.subTab === checkTab;
};
$scope.isSelectedSubLike = function(checkTab){
return $scope.subLike===checkTab;
};
});
For html file look in the plunker link.
Helpful and Reply link are in the reply-link.html file
Here is a Plunker: http://plnkr.co/edit/PQ36lMXR1YOs8DP7WXMk?p=preview
What I did is added helpful: 0 to both comment and reply objects. Also added <p ng-if="object.helpful">{{ object.helpful }} </p> to comment-section.html and reply-box.html
Then when clicking on the helpful added a new function called increaseHelpful(object) where you increase the helpful variable by one on each click. Of course you need to make it that one user can only click it once but just for example :)
Get the index1 also in so you can get the reply box where you click the reply button. Use selectSubTab(index, index1) and then have two variables in $scope.subTab to check what is selected.
Edited from Konkko's plnkr http://plnkr.co/edit/lbn57aPTJQpgzMaQPW6t?p=preview
reply-box.html
<div id ="wrapper">
<form ng-submit="replysubmit()" ng-controller="BlockController">
<div class="clearfix" ng-if="isSelectedSub(index)">
<input type="textarea" tabindex="0"
style="overflow: auto; max-height: 350px; margin-top:1px;" class ="col-sm-8 col-md-8 col-lg-11" ng-model="reply.comment"
name="reply.comment" placeholder="Write a Reply" />
</div>
<blockquote ng-repeat="(index1,object) in replybox">
<h4>Name</h4>
<p>
{{object.comment}} {{index1+1}}
</p>
<p ng-if="object.helpful">{{ object.helpful }} </p>
<ul reply-links></ul>
<div class="clearfix" ng-if="isSelectedSub(index, index1)">
<input type="textarea" tabindex="0"
style="overflow: auto; max-height: 350px; margin-top:1px;" class ="col-sm-8 col-md-8 col-lg-11" ng-model="reply.comment"
name="reply.comment" placeholder="test" />
</div>
</blockquote>
</form>
</div>
reply-links.html:
<ul class="nav nav-pills">
<li>
<a href ng-click="increaseHelpful(object)" class="glyphicon ">Helpful</a>
</li>
<li>
<a href ng-click="selectSubTab(index, index1)" class="glyphicon" >Reply</a>
</li>
</ul>
JS:
$scope.subTab = {first: null, second: null};
$scope.selectSubTab = function(setTab, setTab1){
console.log(setTab);console.log(setTab1);
$scope.subTab = {first: setTab, second: setTab1};
};
$scope.isSelectedSub = function(checkTab, checkTab1){
return $scope.subTab.first === checkTab && $scope.subTab.second === checkTab1;
};