This is my helper for generating a treeview.
Using this i am able to generate the treeview in the mvc5.
#helper GetTreeView(List<MvcTreeview.Models.Category> siteMenu, int parentID)
{
foreach (var i in siteMenu.Where(a => a.ParentID.Equals(parentID)))
{
<li>
#{var submenu = siteMenu.Where(a => a.ParentID.Equals(i.ID)).Count();}
#if (submenu > 0)
{
<span class="collapse collapsible"> </span>
}
else
{
<span style="width:15px; display:inline-block"> </span>
}
<span id="Category">
#i.CategoryName
#*oncontextmenu="return false"*#
</span>
#if (submenu > 0)
{
<ul>
#Treeview.GetTreeView(siteMenu, i.ID)
#* Recursive Call for Populate Sub items here*#
</ul>
}
</li>
}
}
This is my View for displaying
#model List<MvcTreeview.Models.Category>
#{
ViewBag.Title = "Simple";
}
<div class="gridbox gridleft">
<div class="left">
<div style="padding:10px; background-color:#FAFAFA">
<div class="treeview">
#if (Model != null && Model.Count() > 0)
{
<ul>
#Treeview.GetTreeView(Model, Model.FirstOrDefault().ParentID)
</ul>
}
</div>
</div>
</div>
</div>
<div id="onSuccess">
</div>
#* Here We need some Jquery code for make this treeview collapsible *#
#section Scripts{
<script type="text/javascript">
$(document).ready(function () {
$(".treeview li>ul").css('display', 'none'); // Hide all 2-level ul
$(".collapsible").click(function (e) {
e.preventDefault();
$(this).toggleClass("collapse expand");
$(this).closest('li').children('ul').slideToggle();
});
});
function PassingFunction(clicked_id) {
url = '#Url.Action("Details", "TestDetails")';
$.ajax({
url: url,
type: 'GET',
data: { 'id': clicked_id },
success: function (returnData) {
$("#onSuccess").html(returnData);
console.log(returnData);
},
error: {
}
});
}
</script>
}
Now i want to add the custom functionalities to the nodes of the treeview
Add
Delete
Edit
How can i do that?
There is a lot of JQuery Context Menu options on this link.
I have just picked the most forked of them, jQuery contextMenu.
I created a JSFeed fork in an example of treeview using UL/LI and created this JSFiddle with the Context-Menu to help you:
http://jsfiddle.net/mqueirozcorreia/0h82qto6/
Explaining the code:
I have added the externals resources:
http://swisnl.github.io/jQuery-contextMenu/dist/jquery.contextMenu.min.css
https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js
http://swisnl.github.io/jQuery-contextMenu/dist/jquery.contextMenu.min.js
All the magic goes in the javascript code, configuring the context-menu.
The selector property will put the context menu in every element of type <span> and having class attribute with value "contextMenuItem":
selector: 'span.contextMenuItem',
When the user clicks the callback function below runs. In this example, it alerts/logs what key was selected and the id attribute value.
callback: function(key, options) {
var m = "clicked: " + key + " on element of id " + options.$trigger.attr("id");
window.console && console.log(m) || alert(m);
},
Related
I am struggling on adding and removing a style class on a anchor tag. I want to add a active class when I clicked on that tag and remove active from last active one. By default Home page would be active. I have tried many things but no success on that!
I have added few code but it is not working. Below is the code:
angularjs code:
$scope.isActive = false;
$scope.getCSSClass = function () {
return 'active';
}
<div id="mySidenav" class="sidenav">
<span class="whitelogo"><img src="styles/images/logo-small.png" alt="logo"></span>
<div class='clearfix'></div>
×
<a ng-link="['/Home/']" title="Home" class="active"><i class="fas fa-home"></i>Home</a>
<a ng-link="['/TestForm/']" ng-class="getCSSClass()" title="Application Form"><i class="fas fa-user-edit"></i> test Form</a>
</div>
Any help will be appreciated. Thanks in advance!
On Angularjs file, I have added this code:
$scope.getStyleClass = function (path) {
var cur_path = $location.path().substr(0, path.length);
if (cur_path == path) {
if ($location.path().substr(0).length > 1 && path.length == 1)
return "";
else
return "active";
} else {
return "";
}
}
And on Html side:
ng-class="getStyleClass('/TestForm')"
I want send cod to controller and return array
When pressing a li you have to send a code to the controller, in this case I am setting the example 7. Once the code has arrived at the controller I will have a list that I have to show in a ng-repeat in table
SCRIPT
<script type="text/javascript">
var app = angular.module('myApp', [])
app.value('studentInfo', [
{ id: 1, name: 'Mahedee Hasan', credit: 20, semester: '8th' },
{ id: 3, name: 'Enamul Haque', credit: 15, semester: '7th' }
]);
app.controller('myCtrl', ['$scope', 'studentInfo', function ($scope, studentInfo, $http, $window) {
$scope.myClickList = function () {
$scope.studentInfo = studentInfo;
};
var Cod = "7";
$scope.myDataCountry = [];
$scope.ButtonCountry = function (Cod) {
$http.
post("/Country/Angular", { CodH: Cod }).success(function (result) {
$scope.myDataCountry = result;
});
};
}]
);
</script>
VIEW
<li><a data-toggle="tab" href="#calificaciones" ng-click="ButtonCountry ()"><span>Country</span></a></li>
<div ng-app="myApp" ng-controller="myCtrl">
<table class="table">
<tr>
<th>ID</th>
<th>Country</th>
</tr>
<tr ng-repeat="C in myDataCountry">
<td>{{C.ID}}</td>
<td>{{C.Country}}</td>
</tr>
</table>
</div>
CONTROLLER
public JsonResult Angular(string codCountry)
{
var country = (from a in dbCountry.Country
where a.CodPersona == codCountry
select a.Country).ToList();
return Json(country , JsonRequestBehavior.AllowGet);
}
I tried this and to
First, your li element isn't inside your app directive, which means it will not detect the function, you need to make sure that your li element is within the app scope
<!-- li is outside the scope -->
<li><a data-toggle="tab" href="#calificaciones" ng-click="ButtonCountry(1)"><span>Country</span></a></li>
<div ng-app="myApp" ng-controller="myCtrl">
<!-- end -->
<!-- li is within the scope -->
<div ng-app="myApp" ng-controller="myCtrl">
<ul>
<li><a data-toggle="tab" href="#calificaciones" ng-click="ButtonCountry(1)"><span>Country</span></a></li></ul>
<!-- end -->
of course, you need to alter your html elements, meaning ul parent of the li most be included as well.
your Action url is wrong, your controller shows that action name is CalificacionesAngular but you are using Angular for some reason, another thing I notice you never passed the code to your function which means
this
ng-click="ButtonCountry ()"
//should be this
ng-click="ButtonCountry('thecode')"
and the data you are posting isn't similar to the parameter name,
you have to change this
post("/Country/Angular", { CodH: Cod })
//to this
post("/Country/CalificacionesAngular", { codCountry: Cod })
there might be some more issues, these are the one I could see so far, please debug and provide more details about the error you are getting.
A good example you can check as well is this and this, and I suggest reading about Directives, Binding, scope, and Events
I have a element parsed from html template and i want to add a click event to it, it seems not working.
but when i add element like
$('#formatMe').click();
Here click is working but when
var formats = appAPI.resources.parseTemplate("formats.html",result);
$code=$(formats);
$('#vid_div').prepend($code);
But not on element from parseTemplate
I am writing click function in appAPI.ready like below
appAPI.ready(function($) {
$("#user-header").append("<div id='formatMe'>Download</div>");
$('#some-div-in-web-site').append("<div id='vid_div'></div>");
$('#formatMe').click(function(){
var url="myurl";
appAPI.request.get({
url: url,
onSuccess: function (data) {
var result=appAPI.JSON.parse(data);
var formats = appAPI.resources.parseTemplate("formats.html",result);
$('#vid_div').html('');
$code=$(formats);
$('#vid_div').prepend($code);
}
});
});
$('#close').click(function(){
alert("dont'click on me!!!");
});
});
Formats.html is like this
<div id="vid_formats">
<div id="close">×</div>
<div class="wrapper">
<h1>Download Links</h1>
<ul>
<% for (var i=0; i<vids.length; i++) { %>
<li>
<a id="format" href="<%=vids[i]['url'] %>"><%=vids[i]['type']%> <%=vids[i]['quality']%> - <%=vids[i]['size']%> </a>
</li>
<% } %>
</ul>
</div>
</div>
Still not able to fire click event, i am testing in firefox.
Foreword: Since the contents of the formats.html file and result array are not provided and it's also not clear from your example where the element with id close is defined, I created the scenario that I believe you are experiencing.
In the scenario I recreated, the click event handler worked as expected and I can see the alert. The following are the extension files I recreated and then tested in Chrome.
formats.html:
<div>
<ul>
<% for (var i=0; i<sites.length; i++) { %>
<li><%=sites[i].name%></li>
<% } %>
</ul>
</div>
<div id="close">Close</div>
extension.js:
appAPI.ready(function($) {
var result = {
sites:[
{url:' http://cnn.com ', name:'cnn'},
{url:' http://yahoo.com ', name:'yahoo'}
]
},
formats = appAPI.resources.parseTemplate("formats.html",result);
$('<div id="player"></div>').prependTo('body');
$code=$(formats);
$('#player').prepend($code);
$('#close').click(function(){
alert('clicked me');
});
});
[Disclosure: I am a Crossrider employee]
In Meteor, I have an app where I make a list of items grouped by tags, where non-tagged items come first and then tagged items are hidden under a "tag header" drop down.
I haven't touched this app since 0.8 came out, and I was using a block helper in a template which worked fine in pre-0.8...
See working jsfiddle here
Handlebars.registerHelper('eachItem', function(context, options) {
var ret = "";
for(var i=0, j=context.length; i<j; i++) {
if(!context[i].tag){
ret = ret + options.fn(context[i]);
} else {
if(i===0||!context[i-1].tag ||context[i-1].tag !== context[i].tag){
ret = ret + '<li class="list-group-item"><a data-toggle="collapse" data-target="#'+ context[i].tag +'"> Items tagged '+context[i].tag + '</a></li><div id="'+context[i].tag+'" class="collapse">';
}
ret = ret + options.fn(context[i]);
if(i+1<j && context[i+1].tag !== context[i].tag){
ret = ret + '</div>';
}
}
}
return ret;
});
But I'm struggling a bit to translate this into post-0.8 Meteor
The inserted HTML must consist of balanced HTML tags. You can't, for example,
insert " </div><div>" to close an existing div and open a new one.
One idea I had was to render the non-tagged items and also the containers in a vanilla {{#each}} loop (with 2 different templates), and then do something like this
Template.myListContainer.rendered = function(){
_.each(tags, function(tag){
var tagged_items = _.filter(items, function(item){ return item.tag == tag; });
_.each(tagged_items, function(item){
UI.insert(UI.RenderWithData(listItemTemplate, { item : item }), tagContainer);
});
});
}
Is there a simpler way to do this ? If the items come from a collection, will they keep their reactivity ?
Many thanks in advance !
If you haven't already, it's worth reading the Meteor wiki on migrating to blaze.
Anyhow, this one seems difficult to implement as a straight iteration.
If you don't need them in a specific order, I would just list items w/ and w/o tags, eg:
Template.example.helpers({
dataWithoutTags: function(){
return items.find({tag:{exists: false}});
},
tagList: function(){
// create a distinct list of tags
return _.uniq(items.find({tag:{exists: true}}, {tag: true}));
},
dataForTag: function(){
// use `valueOf` as `this` is a boxed-string
return items.find({tag: this.valueOf()});
}
});
Template:
<template name="example">
<div class='panel panel-default'>
<ul class='list-group'>
{{#each dataWithoutTags}}
<li class='list-group-item'>{{name}}</li>
{{/each}}
{{#each tagList}}
<li class="list-group-item">
<a data-toggle="collapse" data-target="#{{this}}"> Items tagged {{this}}</a>
</li>
<div id="{{this}}" class="collapse">
{{#each dataForTag}}
<li class='list-group-item'>{{name}}</li>
{{/each}}
</div>
{{/each}}
</ul>
</div>
</template>
If you do need them in a specific order - eg. grouping only consecutive items (as per your example). The only option would be to pre-process them.
eg:
Template.example.helpers({
itemsGrouped: function(){
dataGroups = [];
currentGroup = null;
items.find({}, {sort: {rank: 1}}).forEach(function(item){
if (currentGroup && (!item.tag || currentGroup.tag != item.tag)){
dataGroups.push(currentGroup);
currentGroup = null;
}
if (item.tag){
if (!currentGroup){
currentGroup = {
group: true,
tag: item.tag,
items: [item]
};
} else {
currentGroup.items.push(item);
}
} else {
dataGroups.push(item);
}
});
if (currentGroup){ dataGroups.push(currentGroup); }
return dataGroups;
}
});
Template:
<template name="example">
<div class='panel panel-default'>
<ul class='list-group'>
{{#each itemsGrouped}}
{{#if group}}
<li class="list-group-item">
<a data-toggle="collapse" data-target="#{{tag}}"> Items tagged {{tag}}</a>
</li>
<div id="{{tag}}" class="collapse">
{{#each items}}
<li class='list-group-item'>{{name}}</li>
{{/each}}
</div>
{{else}}
<li class='list-group-item'>{{name}}</li>
{{/if}}
{{/each}}
</ul>
</div>
</template>
If you log the value you are returning from the eachItem helper, you will see you are not closing the last div element. Fixing that may get it working again. However, you have div elements as direct children of the ul element, which you are not supposed to according to the HTML5 specification:
Permitted contents: Zero or more li elements
Also, I think it would be a better option for you to prepare your context in a format that makes it easier to let simple templates take care of the rendering. For example, using the same data from your jsfiddle, suppose you had it in the following format:
tagGroups = [{
names: ["item1", "item2"]
},{
tag: "red",
names: ["item3", "item4"]
},{
tag: "blue",
names: ["item5", "item6", "item7"]
}]
The following templates would give you the expected result in a valid html format. The ending result is a bootstrap panel containing collapsible list-groups:
<template name="accordion">
<div class="panel panel-default">
{{#each tagGroups}}
{{> tagGroup}}
{{/each}}
</div>
</template>
<template name="tagGroup">
{{#if tag}}
{{> namesListCollapse}}
{{else}}
{{> namesList}}
{{/if}}
</template>
<template name="namesList">
<ul class="list-group">
{{#each names}}
<li class="list-group-item">{{this}}</li>
{{/each}}
</ul>
</template>
<template name="namesListCollapse">
<div class="panel-heading"><a data-toggle="collapse" data-target="#{{tag}}">Items tagged {{tag}}</a></div>
<ul id="{{tag}}" class="panel-collapse collapse list-group">
{{#each names}}
<li class="list-group-item">
{{this}}
</li>
{{/each}}
</ul>
</template>
And here is an example of a helper to transform your data so you can make a quick test to see it working:
Template.accordion.tagGroups = function () {
var data = [{
name : 'item1'
},{
name : 'item2'
},{
name : 'item3',
tag : 'red'
},{
name : 'item4',
tag : 'red'
},{
name : 'item5',
tag : 'blue'
},{
name : 'item6',
tag : 'blue'
},{
name : 'item7',
tag : 'blue'
}];
data = _.groupBy(data, 'tag');
data = _.map(data, function (value, key) {
var obj = {};
if (key !== 'undefined') {
obj.tag = key;
}
var names = _.map(value, function (item) {
return item.name;
});
obj.names = names;
return obj;
});
//console.dir(data);
return data;
};
And yes, if the items come from a collection, you will get reactivity by default.
I am a new ASP.NET Web Forms developer and trying to use Twitter Bootstrap with the Master Page. I am struggling with setting navbar item as active when user selects it. I created my simple master page by following this tutorial about how to use Twitter Bootstrap with ASP.NET.
Here's the code of my master page:
<%# Master Language="VB" CodeFile="MasterPage.master.vb" Inherits="MasterPage" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<link href="css/bootstrap.css" rel="stylesheet" type="text/css" />
<asp:ContentPlaceHolder id="head" runat="server">
</asp:ContentPlaceHolder>
</head>
<body>
<form id="form1" runat="server">
<div>
<div class="container">
<div class="row-fluid">
<div class="span12">
<div class="page-header">
<h1>Hello... My First Website with Twitter Bootstrap</h1>
</div>
</div>
</div>
<div class="row-fluid">
<div class="span3">
<ul class="nav nav-list">
<li class="nav-header">Navigation</li>
<li class="active">ASP.NET</li>
<li>Java</li>
<li>VB.Net</li>
<li>C#</li>
</ul>
</div>
<div class="span9">
<asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</div>
</div>
</div>
</form>
</body>
</html>
Then, I added this script to the Head in order to fix issue with the menu:
<script type="text/javascript">
$(document).ready(function () {
var url = window.location.pathname;
var substr = url.split('/');
var urlaspx = substr[substr.length - 1];
$('.nav').find('.active').removeClass('active');
$('.nav li a').each(function () {
if (this.href.indexOf(urlaspx) >= 0) {
$(this).parent().addClass('active');
}
});
});
</script>
However, nothing has been changed. When I selected any item from the navigation bar, the active class has not been added to the new selected item and I don't know why. Could you please help me in fixing this issue.?
Use this:
<div class="navbar">
<div class="navbar-inner">
<div class="container">
<ul class="nav">
<li class="active">Default</li>
<li>Clients</li>
<li>Display</li>
</ul>
</div>
</div>
</div>
$(document).ready(function () {
var url = window.location;
$('.navbar .nav').find('.active').removeClass('active');
$('.navbar .nav li a').each(function () {
if (this.href == url) {
$(this).parent().addClass('active');
}
});
});
Example: http://jsfiddle.net/yUdZx/3/
And, in the "href" use "Page.ResolveUrl"
Clients
It's better...
Actually Reynaldo, almost had it...
At least for me, this works pretty good, on activing the current option and deactiving the previous one, based on his example.
$(document).ready(function() {
var url = window.location;
$('ul.nav li a').each(function () {
if (this.href == url) {
$("ul.nav li").each(function () {
if ($(this).hasClass("active")) {
$(this).removeClass("active");
}
});
$(this).parent().addClass('active');
}
});
});
For those as myself that prefer server-side implementations, transform your li tags of interest to runat="server" on the Master.Page file. The code in question will look something similar to this:
<div class="collapse navbar-collapse" id="menu">
<ul class="nav navbar-nav ml-auto">
<li class="nav-item" runat="server" id="tabHome" >
<a class="nav-link" href="/">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item" runat="server" id="tabContact">
<a class="nav-link" href="/Contact">Contact</a>
</li>
<li class="nav-item">
<a class="nav-link" runat="server">Hello, <asp:LoginName runat="server" />
</a>
</li>
</ul>
</div>
Then in the code behind of the Master page - Site.Master.vb or Site.Master.cs, depending on the language used - add the following in the Page Load event:
VB.Net implementation:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Load
Dim thisURL As String = Request.Url.Segments(Request.Url.Segments.Count - 1)
Select Case thisURL
Case "Default", "default.aspx"
tabContact.Attributes.Remove("active")
tabHome.Attributes.Add("class", "active")
Case "Contact"
tabHome.Attributes.Remove("active")
tabContact.Attributes.Add("class", "active")
End Select
End Sub
C# implementation:
Protected void Page_Load(Object sender, EventArgs e)
{
string thisURL = Request.Url.Segments[Request.Url.Segments.Length - 1];
switch (thisURL)
{
Case "Default":
Case "default.aspx":
{
tabContact.Attributes.Remove("active");
tabHome.Attributes.Add("class", "active");
break;
}
Case "Contact" :
{
tabHome.Attributes.Remove("active");
tabContact.Attributes.Add("class", "active");
break;
}
}
}
Since is "Default.aspx" the page that is supposed to be opened initially, the "Home" menu item will be highlighted as soon the user enters the website. An example is displayed below:
For the sake of simplicity, only two navbar items were used in the example, but the same logic could be implemented if more are required.
I hope can be of help.
I've placed this in each one of my content pages, changing the id of the nav item for each page (this uses JQuery selectors). So for this to work for you you'll need to give your list items an Id. I don't add the "active" class to the master page because all we need to do is highlight the appropriate one when the content loads.
<script language="javascript" type="text/javascript">
$(document).ready(function () {
$("[id$=yourNavItemId]").addClass("active");
});
</script>
Note: if you're using ASP.NET controls instead of list items inside of your nav bar, they might be getting prefixed at runtime causing your javascript not to find the Id you think you're looking for.
following code works if I have subpages:
$(document).ready(function () {
$('.navbar .nav').find('.active').removeClass('active');
var url = window.location.toString();
var u = url.substring(0, url.lastIndexOf("/")).toString();
$('.navbar .nav li a').each(function () {
var hr = this.href.substring(0, this.href.lastIndexOf('/')).toString();
if ((u == hr) || (u.indexOf(hr) > -1))
{
$(this).parent().addClass('active');
return false;
}
});
// Deactivation to manually add items you have with href = "#" example:
$('#liSalir').removeClass('active');
});
If you are using navigation bar with dropdown-menu then put below script at end of your master page(before body closing tag):
<script type="text/javascript">
$(document).ready(function () {
var url = window.location;
$('ul.nav li a').each(function () {
if (this.href == url) {
$("ul.nav li").each(function () {
if ($(this).hasClass("active")) {
$(this).removeClass("active");
}
});
$(this).parent().parent().parent().addClass('active');
}
});
});
</script>
This completely worked for me.
I know this post is old but use
$(document).ready(function () {
var url = window.location;
$('ul.nav li a').each(function () {
if (this.href == url) {
$("ul.nav li").each(function () {
if ($(this).hasClass("active")) {
$(this).removeClass("active");
}
});
$(this).parents().addClass('active');
}
});
});
Since you also wants to active the all the parents.
var windowUrl = window.location.href.toLowerCase();
//var windowUrl = window.location.href.toLowerCase().split('.')[0];
setTimeout(function () {
var windowUrl = window.location.href.toLowerCase();
$('#nav li').removeClass('active');
$('#nav li').each(function (index) {
pageUrl = $(this).find('a').attr('href');
if (windowUrl.indexOf(pageUrl) > -1) {
$(this).addClass('active');
}
});
}, 10);
I have created a sample which full fill your requirement you need to modify the code according to your need.
Use this jquery on master page
<script type="text/javascript">
$(function () {
$('[id*=submenu]').addClass('sub-menu open');
$('[id*=Master_Pages]').attr("aria-expanded", true);
$('.subMenus').click(function () {
localStorage.setItem('lastTab', $(this).attr('id'));
});
});
function pageLoad() {
var isActiveLink = false;
$.each($('.subMenus'), function () {
if ($(this).attr('id') == localStorage.getItem('lastTab')) {
$(this).closest('li').addClass('active');
localStorage.removeItem('lastTab');
isActiveLink = true;
}
else {
$(this).closest('li').removeClass('active');
}
});
if (!isActiveLink) {
$('[id*=Master_Designation]').closest('li').addClass('active');
}
}
</script>
Some helpful article for .Net guys
https://gist.github.com/josephwambura/ef97b44c309226301847d3e09e0e2562?permalink_comment_id=4381643#gistcomment-4381643