Adding items dynamically/programmatically to jQuery-ui sortable - javascript

I have some jQuery UI Portlets similar to this:
http://jqueryui.com/sortable/#portlets
and what I want is to add dynamically (when user click on a button on the UI) some boxes like this (display as grid) within each portlet:
http://jqueryui.com/sortable/#display-grid
I want to add them to portlet from top to bottom and from left to right, defining the maximum number of "boxes" (items) per row.
Is it possible to do (dynamically add them to each portlet)? if so, how? some ideas?
for example, let's say I have below jquery-ui sortable block in my asp.net mvc4 view (initially empty):
<ul id="sortable">
</ul>
so when user click on a button, I want to add an item Text01 like this:
<li id="Text01" class="ui-state-default">Text01</li>
so after adding it, below sortable block is:
<ul id="sortable">
<li id="Text01" class="ui-state-default">Text01</li>
</ul>
if user click on a button again, I want to add another item to the sortable block, so after adding it, below sortable block is generated:
<ul id="sortable">
<li id="Text01" class="ui-state-default">Text01</li>
<li id="Text02" class="ui-state-default">Text02</li>
</ul>
and so on...
Note that in this example ids and contents are correlative, Text01, Text02... but this is only an example, ids and contents can be different.
Any ideas on how to do this from a jquery function?
I am using jQuery 1.10.2

This looks promising:
http://api.jqueryui.com/sortable/#method-refresh
I haven't tried it, but it seems to imply that you can just add an item to a sortable, then call $('#mysortable').sortable('refresh') to recognize it.

This works. Call appendThing from your button click:
var counter = 1;
function appendThing() {
$("<li id='Text" + counter + "' class='ui-state-default'>Text" + counter + "</li>").appendTo($("#mySortable"));
$("#mySortable").sortable({ refresh: mySortable })
counter++;
};

Related

Javascript - How to highlight the last clicked list item

I have a sidebar list of items in HTML on a bootstrap page and i would like the last clicked item to be highlighted with a "active" class. I was wondering how i can get the whole list (ul) like an array so i could highlight a certain item (li) or highlight the last clicked item.
The list is structured like this:
<div class="container-fluid">
<div class="row">
<div class="col-sm-3 col-md-2 sidebar sidebar-style">
<ul class="nav nav-sidebar sidebar-scrollable">
<li class="active">Home</li>
<li>Site 001</li>
<li>Site 002</li>
<li>Site 003</li>
<li>Site 004</li>
<li>Site 005</li>
What i need is some JS code which can set the last clicked li item to class="active" but still have the option to set any of the li items to the active one, for example if i wanted to have a random button and it selected item 4 then 2 etc. I guess the main thing i need is a way to have all list items like an array.
I strongly suggest you use jQuery which is kind of simulating DOM manipulation like an array or more precisely an object.
My suggestion would be the following:
$(".nav-sidebar").on('click', 'li', function(e) {
$(this).parent().find('li.active').removeClass('active');
$(this).addClass('active');
});
This code is removing the active class from all li items, and adding active class to currently clicked li item.
Cheers,
Edit PS:
You could also bind your event directly like this:
$(".nav-sidebar li").click(...);
But the purpose of using .on() is that it will bind the event dynamically, so that if you decide to add a new li to your $(".nav-sidebar") element, it will also trigger the event on that element.
Edit:
To answer #zeddex your question: How to select manually li 4?
You simply use the following:
$("li:eq(3)").trigger('click');
That'll manually trigger a click event for li 4. If you want to select a specific li you can use a method of the like: :eq(x) in which x is the position of the li item you want to reach starting from 0 which corresponds to your first li. Have a look at jQuery DOC on that: jQuery DOC on :eq()

Backbone.js – changes to li element don't display immediately

What I have in my template is just a bunch of divs and a list, consisting of multiple li elements. The use case is simple, the li elements are a dropdown and are displayed only on clicking a button. When the dropdown is visible and someone begins to type, the matching li element should be selected, or there should be a visual indication.
My approach is this, on a keyup event, I look for the typed word (this is quite easy) in the li elements. I find a few elements, which I've confirmed. Now, when I try to do something with these elements, nothing seems to happen WHILE the dropdown is open (right now, I'm trying to .toggle()) these elements. Now, when I click the button again (which showed the dropdown in the first place) (this click hides the dropdown), and then click the same button again to reveal the dropdown, voila! The values have been changed as they should be – the matching elements have been hidden/shown.
This has me stumped. For company policies, I can't upload the code up here, but I'll be very thankful if someone else has had this problem before and can help me out.
EDIT:
Code: function to change the dropdown on keypress, this is being fired correctly:
filterOptionsForKeypress: function (event) {
var typedString = this.$('input.filter-button-text').val(),
searchToken = _.trim(typedString.toLowerCase().replace(/ /g, '_')),
matchingLi = this.$("li[data-field^='" + searchToken + "']", this.$el), // makes no difference with or without the context, this.$el
that = this;
if (matchingLi && matchingLi.length) {
this.$(matchingLi[0]).html('kaka'); // this change shows only if the dropdown is hidden + shown again
console.log('trying to move focus', this.$(matchingLi[0]).attr('data-field'));
}
// this.$el.append('Some text'); -- this works, I see the changes as they happen
}
And the template looks something like this:
<div class="filter-button filter-option {{if !model.include}}button-red{{else}}button-green{{/if}} toggle-dropdown" data-dropdown-class="{{if !model.include}}button-red{{else}}button-green{{/if}}">
<div class="filter-button-text">${model.option}</div>
<div class="filter-drop"></div>
<div class="dropdown filter-dropdown">
<ul>
{{each model.config.options}}
<li data-field="${$value.op}" data-include='${$value.include}'>${$value.name}</li>
{{/each}}
</ul>
</div>
</div>
EDIT #2:
When the dropdown is open, this is how the html looks:
OPEN:
CLOSED:
So basically, apart from adding a few styles to the enclosing div and a class 'open', I don't see any differences.
The problem was that we're using a plugin for dropdown menus. So basically, what we saw on the screen wasn't what we found selecting with this.$(). The solution? Look globally and with a :visible filter voila, problem solved.

Table made from list (<ul>,<li>), how to select a row? (:nth-child())?

I made a table out of a simple list structure:
<html>
<body>
<ul id="Column:0">
<li id="Row:0></li>
<li id="Row:1></li>
<li id="Row:2></li>
<li id="Row:3></li>
<li id="Row:4></li>
</ul>
<ul id="Column:1">
<li id="Row:0></li>
<li id="Row:1></li>
<li id="Row:2></li>
<li id="Row:3></li>
<li id="Row:4></li>
</ul>
<ul id="Column:2">
<li id="Row:0></li>
<li id="Row:1></li>
<li id="Row:2></li>
<li id="Row:3></li>
<li id="Row:4></li>
</ul>
</body>
</html>
Now I want to add a simple .mouseover() to every row, for e.g. changing the color of a row, when hovered. And this is what I figured out, so far:
for (var i = 2; i <= _totalRows; i++) {
var row = $('#TimeTable ul li:nth-child(' + i + ')')
row.each(function() {
$(this).click(function(evt) {
var $target = $(evt.target);
console.log($target.nodeName)
if (evt.target.nodeName == 'DIV') {
console.log(evt.parent('li'));
}
}); //end $(this).click(fn)
}); // end each(fn)
}
I get a set of all <li> objects matching to :nth-child(i) where i is the rows number.
var row = $('#TimeTable ul li:nth-child(' + i + ')')
Now I just iter this set through to add a .click(fn) to every <li>.
This works fine. Every cell has it's .click(fn) attached to it.
But the following, what to do on a click, is where I'm stuck for several hours now:
var $target = $(evt.target);
console.log($target.nodeName)
if (evt.target.nodeName == 'DIV') {
console.log(evt.parent('li'));
}
I simply don't get it to run.
You can actually ignore this gibberish, as it's just the last of several things I already tried here.
What I'm trying to do is simply select every <li> with an id='Row:X' and manipulate its CSS. The best I yet had was, that I can click a cell, but no matter in what row this cell is, the last one gets colored. I remember having used i as the row-index, when that happened, so I might miss some understanding of event-handling here, too.
Use a class name for duplicate groups of elements not an ID. If you give row one a class of "Row1" the selector is simply:
$('.Row1')
Then:
$('#TimeTable li').removeClass('highlight');
$('.Row1').addClass('highlight');
If you just wish to change the color on mouseover:
$('#TimeTable ul li').mouseover(function(){
$(this).css('background','red');
});
$('#TimeTable ul li').mouseout(function(){
$(this).css('background','green');
});
Make your ID's like so: C1R1 (Column1Row1) and so on
JQuery read/google up "jquery each"
JQuery read/google up "jquery bind click"
JQuery read/google up "jquery attr" and "JQuery val()"
This will give you the knowledge to write your own and most importantly understand it better. You will want to achieve the following (your close but no for loop required):
A list which JQuery attaches a click event handler to each LI, and then when the click happens the ID can be retrieved.
PS. There's a time and place for tables, they 9/10 times nearly always better for displaying data than CSS is. If you have a complex multi column row and want fiexed hights and no JS to fix things or do anything smart you can have a table and css :Hover on TR for stying mouse over and out etc. Heights are also constant.
PS. PS. If your data is dynamic and coming from a database and the whole row is an ID from the database I tend to avoid using the html ID attribute for this and make my own. You can retrieve this via attr("myattribute");
NOTE ON CSS and IDS:
Standard practice for ID's are to be used once on a page.
Class for repeatable content
Good luck.

Parallel sorting two different lists using jquery sortable

I am having very specific case where I needed to split the data into two different lists in html. Like this:
<ul id="first_list">
<li ref="1">The quick brown</li>
<li ref="2">My father works</li>
</ul>
And the second list is like:
<ul id="second_list">
<li ref="1">jumps over the lazy dog</li>
<li ref="2">at the Ministry of Defense</li>
</ul>
So as you can see I from the "ref" attribute I know which <li> element from the second list is a continuation of which <li> element from the fist list.
Now I need to enable the jQuery UI sortable() to those lists but when I reorder the first I need the second reordered too. I tried using handle but it doesn't works because it looks like the handle element needs to be inside the element which is moved but these two are at a different places in the page.
I do believe that you should have shared some of your code (what you've tried), and I'm assuming you are familiar with Sortable plugin that you are using. You should run the below code on success event of Sortable so as soon as you sort any LI, the other list will be sorted too. Anyways,
Try this:
//This line stored the LIs in a temp variable and remove it
var $cachedList = $('<div />').html($('#second_list').html());
$('#second_list > li').remove();
//This line loads up the first UL's LIs and replaces the content for each LI
//using $cachedList.
$('#second_list').html($('#first_list').html()).find('li').each(function () {
$(this).html($cachedList.find('li[ref="'+$(this).attr('ref')+'"]').html());
});
Demo: http://jsfiddle.net/AR8px/

Losing dropdown list info on mouseout

I have built a simple dropdown list which I populate with various links. It contains about 50 items, so I wrapped it in a div to make it scrollable. Problem is, when I mouseout, I lose the whole list, unless the first two list elelments are showing. I have constructed this dropdown as a submenu, with the first two links as the 'container' of sorts.
I somewhat understand why I am losing the entire list, but can't figure out how to make the top links reapear on mouseout.
$('.myMenu > li').bind('mouseover', openSubMenu);
function openSubMenu() {
$('.myMenu').css('overflow','auto');
$('.myMenu').css('height','400px');
$('.ulMenu').css('visibility', 'visible');
};
$('.myMenu > li').bind('mouseout', closeSubMenu);
function closeSubMenu() {
$('.myMenu').css('overflow','hidden');
$('.myMenu').css('height','20px');
$('.ulMenu').css('visibility', 'hidden');
}
}
</script>
<div id="menu">
<ul class="myMenu">
<li id="li_left"> Application </li>
<li id="li"> Hover For Listing
<ul id="tasksUl" class="ulMenu">
</ul>
</li>
</ul>
</div>
I think you also have to post your .css for the list. I think you got a menu and you wanna open a list on hovering <li id="li"> Hover For Listing
You are setting a
$('.myMenu').css('height','20px');
and I don't get why you would do that. Also your .css styles are pretty much deprecated.
Check the fiddle here: http://jsfiddle.net/eR2y9/1/
Works like a charm. There is no need for you to add a height for the menu because it's dynamically adjusting depending on the amount of entries inside. Also if set to display none it's not taking any space away.. If you have further questions or if I misunderstood your problem feel free to reply to my post and I will find a solution for ya.

Categories