How do I data-bind = "visible : active" in div - javascript

hi this is my code snippet:
<div class="showtimes" data-bind="visible: showHide">
<div data-bind="template: { name: 'movie-grouped-showtimes-template', data: $data }"></div>
</div>
I want to toggle showHide off and on using the following:
<a class="icon arrow" data-bind="click: $parent.showtimes">
can't I just set up a variable showHide in my view Model, like the following:
self.showHide = ko.observable(false) ... Hide
showHide(true); ... show
and can I set it using the click : $parent.showtimes, like in the following:
<a class="icon arrow" data-bind="click: $parent.showtimes"></a>

You just have to set a function in the viewmodel that binds to the button's click (or modify an existing one, like showTimes in this case) to toggle the value of showHide.
Here's a simple example: http://jsfiddle.net/EfrainReyes/LNzDL/
var vm = {
showHide: ko.observable(false),
toggle: function() {
this.showHide( !this.showHide() );
}
};
ko.applyBindings(vm);
I didn't add any other elements to the example because the question seems to be targeted more towards showing/hiding the div.

Related

Inserting script for bootstrap popover

I have a bootstrap 4 popover with list inside which comes from a viewcomponent element (asp net core 3.1 project).
This popover is inside layout navigation bar (not sure if that's relevant) and after hovering over it the list should appear.
Now every list element appears correctly but after I click any of the list elements I want to send ajax post request but I cannot make my javascript work. I am not sure what is the problem. Is it because my script is only loaded when I hover on popover? Am I using events incorrectly? I tried a lot of variations to test if JS is working and seems like everything failed.
ViewComponent:
#model mymodel;
<div class='list-group'>
#foreach (var item in Model.Item)
{
<a href='#item.Url' class='btn list-group-item list-group-item-action mb-1'>You have been invited to join event: <b>#item.Name</b></a>
}
#foreach (var item in Model.AnotherItem)
{
<a id='lmao' href='#' onclick='doSomething(#item.Id);' class='list-group-item list-group-item-action mb-1'>You have been invited to join team: <b>#item.Name</b></a>
}
</div>
<script>
$('#lmao').click(function () { MyFunction(); return false; });
function MyFunction() {
alert('hello');
console.log(data);
console.log(this);
}
</script>
_Layout Page with popover:
<div class="navbar-collapse">
<ul class="navbar-nav">
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" data-toggle="dropdown">
Settings
</a>
...
<a tabindex="0" class="dropdown-item pop" data-container="body" data-html="true" title="Your invitations" data-toggle="popover" data-placement="left" data-content="#await Component.InvokeAsync("InvitationList")" style="cursor: pointer;">Invitations (number coming from another viewcomponent)</a>
...
</div>
</li>
...
Popover JS in Layout:
<script>
$('.pop').popover({
trigger: 'manual',
html: true
})
.on('mouseenter', function () {
var _this = this;
$(this).popover('show');
$('.popover').on('mouseleave', function () {
$(_this).popover('hide');
});
}).on('mouseleave', function () {
var _this = this;
setTimeout(function () {
if (!$('.popover:hover').length) {
$(_this).popover('hide');
}
}, 300);
});
</script>
My popover works correctly, I see the items loaded from viewcomponent, I can press on each of them and go to preset href.
What doesn't work is javascript coming from viewcomponent or atleast I am failing to test it. My end goal is to make a post call if any of the items in the popover are clicked.
I tested your codes and found if you directly call viewcomponent in data-content, the jacascripts in ViewComponent will be recongnized as html, so it will never be called. Instead, you can define an area for viewcomponent separately
<a id="invitations" tabindex="0" class="dropdown-item pop" data-container="body" data-html="true" title="Your invitations" data-toggle="popover" data-placement="left" style="cursor: pointer;" data-content="">invitations</a>
<div id="vc" style="display:none">
#await Component.InvokeAsync("InvitationList")
</div>
Use js to append it to data-content
$("#invitations").attr("data-content", $("#vc").html())
Since it is a new element from other page, the handler won't be bound on that new element, your click function should be like this:
<script>
$('body').on('click', '#lmao', function () { MyFunction(); return false; });
function MyFunction() {
alert('hello');
console.log(data);
console.log(this);
}
</script>
Test result:

Jquery show text on hover - Looped Item

I am needing to show text for an icon when it is hovered on. The issue is the icons are displaying via a loop. Meaning I have more than one icon with the same name. I'm sure I need to use "this" somehow to only show text next to the icon that is hovered on. However so far I have failed to do so.
My basic code so far. How would I change the code to show text depending on which icon is being hovered on?
$(".material-icons").on({
mouseenter: function () {
console.log('Show Name for this Icon')
},
mouseleave: function () {
console.log('Hide Name for this Icon')
}
});
Any help is appreciated!
Edit: Here is the loop that's being used to show the icons.
<li id='topSection' class="list-group-item active">Amenities </li>
<li id="amnetiesBox" class="list-group-item">
<% for(var i=0; i<rentals.amenities.length; i++){ %>
<i class="material-icons"><%=rentals.amenities[i]%></i>
<% } %>
</li>
</li>
An example of the icons being selected:
<input type="checkbox" name="amenities" value="personal_video"><span>TV</span>
<input type="checkbox" name="amenities" value="call"><span>Phone</span>
You can use $(this) and display the text related to that target element
$(".material-icons").on({
mouseenter: function () {
$(this).next("span").show()
},
mouseleave: function () {
$(this).next("span").hide()
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="material-icons" ><span>Hover </span></div> <span style="display:none">first</span>
<div class="material-icons" ><span>Hover</span></div> <span style="display:none">second</span>
<div class="material-icons" ><span>Hover</span></div> <span style="display:none">third</span>
I came up with a somewhat simple solution that works. The problem with the other suggestions is that I cant add spans per icon because of the loop (as far as I know.)
I went with this:
$(".material-icons").on({
mouseenter: function () {
var text = $(this).text();
if (text === 'wifi'){
text = 'Local Wifi'
}
if (text === 'local_laundry_service'){
text = 'Laundry on site'
}
$(".showName").show()
$(".showName").html(text)
},
mouseleave: function () {
$(".showName").hide()
}
});
So what it's doing is finding the icons name first and if the icon name is "local_laundry_service" etc I'm updating the text to say simply Laundry on site. Obviously you have to do this for each icon that might be used. Not very dry code but I'm not sure how else to go about it.

Knockout foreach dynamically set ID

I just started using knockout and having some problems using foreach.
I need to dynamically populate a list with "collapsing" div.
I cant figuer out how to set the
"data-target=""" with the according div id.Is there a kind of $index as in Angular.How do i declare it inside of the data-target?
Thank for the help.
<ul class="nav navbar-nav side-nav">
<li data-bind="foreach: { data: categories, as: 'category' }">
<div id="??" class="collapse">
<h1>Some text</h1>
</div>
</li>
</ul>
Do it within the data-bind:
<a href="javascript:;" data-toggle="collapse" data-bind="attr: { 'data-target': ... }">
<div class="collapse" data-bind="attr: { id: ... }">
Knockout does have a $index context property, too:
<div data-bind="attr: { id: 'foo' + $index() }">
What's data-target being used for? I don't think you not need that in the first place.
If you want to toggle a section, I recommend using a more natural way to solve this. In the context of knockout this means: write a binding handler that encapsulates the behavior you want.
Expressed in simplest terms: You want to click on something and it should toggle something else. For example the visibility of the following <h1>
The minimal thing to do would be: Toggle a CSS class and use that to influence visibility.
Here is a binding handler that switches a CSS class on and off. Together with the simplest CSS you get collapse/expand behavior.
ko.bindingHandlers.toggleClass = {
init: function (element, valueAccessor) {
ko.utils.registerEventHandler(element, 'click', function () {
var cssClass = valueAccessor(),
shouldHaveClass = element.className.indexOf(cssClass) < 0;
ko.utils.toggleDomNodeCssClass(element, cssClass, shouldHaveClass);
});
}
}
ko.applyBindings({
categories: [
{title: 'Category A'},
{title: 'Category B'},
{title: 'Category C'},
{title: 'Category D'}
]
});
.collapsed+.collapse {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: categories">
<li>
<div class="collapse">
<h1>Some text</h1>
</div>
</li>
</ul>
Of course you can use all kinds of more advanced techniques, but the principle would stay the same. Define a behavior, attach that behavior to an element via a binding handler.

accessing angular HTML from custom controller

OK, I have a custom template I am using where i have several accordions containing lists where the user can click on the option and it becomes active. However I cannot access the parent scope in the controller to change remove the active class from the previously clicked item.
Basically what I want is when a user clicks on a list item, it becomes active and the other items become inactive.
Here is the plunker: http://plnkr.co/edit/d5kHjH?p=preview
Here is the pertinent code:
.run(function(formlyConfig) {
formlyConfig.setType({
name: 'label',
template: `<div ng-init= "active = false">
<a li class="list-group-item small" ng-click="addActive(); active = !active" ng-class="{'active': active === true}"><span class="glyphicon glyphicon-chevron-right"></span> {{to.label}}</li></a>
</div>`,
controller: function($scope) {
$scope.addActive = function() {
$(this).parent().children().removeClass("active");
$(this).addClass("active");
$scope.model.PROC = $scope.to.label;
console.log($scope.model.PROC);
};
}
});
})
I want to be able to add the inactive class to the previously created items, which are being called from an ng-repeat from here in the HTML:
<uib-accordion close-others="true">
<ul class="list-group">
<div uib-accordion-group="" class="panel-primary" ng-repeat="accordion in vm.accordions" active="accordion.active" is-open="isopen">
<uib-accordion-heading ng-click="isopen=!isopen">
<span class="label label-info pull-left">{{accordion.label}}</span>
{{accordion.title}}
</uib-accordion-heading>
<formly-form model="accordion.form.model" fields="accordion.form.fields" form="vm.form" options="accordion.form.options"></formly-form>
</div>
</ul>
</uib-accordion>
The formly-form line is where the template item are being added in on by one

Bootstrap custom popover

Is it possible to have a custom bootstrap popover?
I mean I want to be able to use
$('#example').popover(options)
So on click of an element #example, I'll pass some text (which would be shown in editable textarea);
I am using bootstrap 2.3.2
I dont think the links in the comments completely answers the question. Here is a 2.3.2 example, working with multiple links / elements, that passes text() from the element to a textarea on the popover, and back to the element upon "submit" :
awesome user
Use popovers template feature to customize the popover (adding buttons), set a <textarea> as content, inject the text of the link / element to the textarea on the shown event :
$("[rel=comments]").popover({
trigger : 'click',
placement : 'top',
html: 'true',
content : '<textarea class="popover-textarea"></textarea>',
template: '<div class="popover"><div class="arrow"></div>'+
'<h3 class="popover-title"></h3><div class="popover-content">'+
'</div><div class="popover-footer"><button type="button" class="btn btn-primary popover-submit">'+
'<i class="icon-ok icon-white"></i></button> '+
'<button type="button" class="btn btn-default popover-cancel">'+
'<i class="icon-remove"></i></button></div></div>'
})
.on('shown', function() {
//hide any visible comment-popover
$("[rel=comments]").not(this).popover('hide');
var $this = $(this);
//attach link text
$('.popover-textarea').val($this.text()).focus();
//close on cancel
$('.popover-cancel').click(function() {
$this.popover('hide');
});
//update link text on submit
$('.popover-submit').click(function() {
$this.text($('.popover-textarea').val());
$this.popover('hide');
});
});
see fiddle -> http://jsfiddle.net/e4zMu/ here with three editable links / elements :
In the event you want to use RAZOR or HTML actually be used as the template for the popover (rather than injecting it through the attribute in JS):
In the following example, we were building a bootstrap Breadcrumb control with a popover that contained a list of values that might be selected to change the value of a breadcrumb.
we were using razor to create the HTML TEMLPLATE for the popover-content.
This is how the popover used HTML for its 'content':
<script type='text/javascript'>
$(function () {
$('a[data-toggle="popover"]').popover({
html: true,
content: function () {
return $($(this).data('contentwrapper')).html();
}
});
});
</script>
What this did was for the content attribute, we used jquery to search for a data-contentwrapper within this breadcrumb.
We used Razor to create each breadcrumb element (using orderlist / listitem) and a div containing the proper id to be used in our data-toggle.
<ol class="breadcrumb">
#foreach (var segment in Model.Segments)
{
var selectedChild = segment.SelectedChild;
var popoverId = segment.Id + "_breadcrumb_popover";
var longCaption = segment.Caption;
var shortCaption = segment.Id;
var childType = segment.ChildType;
if (segment.SelectedChild != null)
{
shortCaption = segment.SelectedChild.Id;
}
else
{
// if the selected child is null, then we want the text to show 'select ' _grandchildType is
shortCaption = string.Format("Select {0} ?", segment.ChildType);
}
var listItemClassString = (segment.Children.Any()) ? "" : "hidden";
<!-- THIS IS THE BREADCRUMB ELEMENT -->
<li class="#listItemClassString">
<small>#childType</small>
<a href="javascript: void(0)" tabindex="0" rel="popover" data-container="body"
data-html="true" data-toggle="popover" data-placement="bottom"
data-animation="true" data-trigger="focus" title="Choose #childType" data-contentwrapper="##popoverId" >#shortCaption</a>
<i class="glyphicon glyphicon-chevron-right"></i>
</li>
<!-- THIS IS THE TEMPLATE DROPDOWNLIST FOR THe above list item -->
<div role="tooltip" title="FROM TEMPLATE" class="popover breadcrumb hidden" id="#popoverId">
<div class="arrow"></div>
#*<h3 class="popover-title"></h3>*#
<div class="popover-content" class='panel clearfix hidden' style='padding-right: 10px;'>
<ul class="list-group">
#foreach (var option in segment.Children)
{
<li class="list-group-item">
#{
var url = new UrlHelper(ViewContext.RequestContext, RouteTable.Routes).RouteUrl("DefaultWithBreadcrumb",
new
{
action = parentRouteData.Values["action"] as String,
controller = parentRouteData.Values["controller"] as String,
breadcrumbPath = option.Url
});
}
#option.Caption
</li>
<!-- class='col-md-3 col-sm-4'-->
}
#{ tabIndex++;}
</ul>
</div>
</div>
}
</ol>
Hope this helps someone who would like to combine serverside MVC with clientside bootstrap popover html content.

Categories