I have a nested set of objects I would like to sort. The first example, directly below, is my prototype / test. It works nicely. The outer groups sort, and the inner groups sort. the inner groups are locked inside - cant be moved outside. Just exactly like i want...
<div id="example5">
<ul class="table">
<li class="group" style="width:300px;">Group 1
<ul style="padding:0px;">
<li class="field">Group 2</li>
<li class="field">Group 3</li>
</ul>
</li>
<li class="group">Group 2</li>
<li class="group">Group 3</li>
<li class="group">Group 4</li>
</ul>
</div>
And
$("#example5 ul").sortable({
});
This is the same structure I am trying to impart in my program. Everything seems the same to me, just with some added complexity. Clearly, I am breaking it somehow. The outer groups sort, while the inner ones do not.
I think its important to note that in the previous example, the script and html are in the same file. In the second example, below, the html is dynamically created with createElement() function
<div id="logtable">
<ul id="ultable" class="table ui-sortable">
<li id="" class="groupcontainer" style="width:auto; margin:2px;">
<ul>
<li class="fieldcontainer">
<div class="fieldname"></div>
<div class="fieldgroup"></div>
<div class="fieldname"></div>
<div class="fieldname"></div>
<div class="fieldname"></div>
</li>
</ul>
</li>
<li id="a" class="groupcontainer" style="margin: 2px;"></li>
<li class="groupcontainer" style="margin: 2px;"></li>
</ul>
</div>
Javascript:
$(function() {
var fieldstart;
var fieldend;
$("#logtable ul").sortable({
start: function(event, ui) {
fieldstart = ui.item.index();
},
update: function(event, ui) {
fieldend = ui.item.index();
var fieldcount = jsonstring.tracelog.fields.length;
var fieldobjects = jsonstring.tracelog.fields;
var placed = false;
jsonstring.tracelog.fields.move(fieldstart, fieldend);
writejson();
}
});
});
Following up, this site... http://www.trace-log.com/sortworks.php is copied from the "inspect element" output. it works exactly like i want. http://www.trace-log.com is the site i generated it from. basically, add a value to the field name, it will generate a new field. entering a value in the first text box will initiate the "grouping" of fields. cant understand why this isn't working.
so as it stands, it works if i statically recreate the page, but doesnt work correctly on the dynamically created page. could it be somehow with the way the sortable function is being called?
In the second example the field container is an li and the field names are div tags. The first example you had the field container as an ul tag and the fields as li. I think this might be your issue.
see fiddle here http://jsfiddle.net/4Mk4K/3/
You can try adding a custom class to the elements you want to be sortable and then use that class in the items option of sortable.
Demo:http://jsfiddle.net/lotusgodkk/GCu2D/161/
HTML:
<div id="logtable">
<ul id="ultable" class="table ui-sortable">
<li id="" class="groupcontainer item" style="width:auto; margin:2px;">Z
<ul>
<li class="fieldcontainer">
<div class="fieldname item">A</div>
<div class="fieldgroup item">B</div>
<div class="fieldname item">C</div>
<div class="fieldname item">D</div>
<div class="fieldname item">E</div>
</li>
</ul>
</li>
<li id="a" class="groupcontainer item" style="margin: 2px;">F</li>
<li class="groupcontainer item" style="margin: 2px;">G</li>
</ul>
</div>
JS:
$(function () {
var fieldstart;
var fieldend;
$("#logtable ul").sortable({
items: '.item',//Custom class of items which needs to be sorted.
start: function (event, ui) {
fieldstart = ui.item.index();
},
});
});
After much fiddling and fussing, relocating the sortable function into the function that creates the DOM objects solved the problem. I think the way it was originally structured, some DOM objects were created AFTER the sortable function - and sortable didn't know they existed.
So yes, there was something else structurally wrong with my code. Thanks everyone for the help.
Related
I'm trying to append child html of li into div.row. First time function is working properly but second time it does not works, however i'm using same classes for jquery selector.
I searched about it and found jquery delegate(), i have also tried with it and jquery on('click','',function(){...}); but both are not working with appended function.
$( "body" ).delegate( ".list-group li a", "click", function(event) {
event.preventDefault();
if ( $(this).parent().children('ul').length > 0 ) {
$('.append-level').append(
'<div class="col-md-3 col-xs-12 col-sm-6">'+
'<h2>Child List Group</h2>'+
$(this).parent().children('ul').html()+
'</div>');
}
});
.hide-child{display:none}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="row append-level">
<div class="col-md-3 col-xs-12 col-sm-6">
<h2>Parent List Group</h2>
<ul class="list-group" id="level-one">
<li class="list-group-item">First item</li>
<li class="list-group-item">Second item</li>
<li class="list-group-item">Third item
<ul class="list-group hide-child">
<li class="list-group-item">First item</li>
<li class="list-group-item">Second item</li>
<li class="list-group-item">Four Third item
<ul class="list-group hide-child">
<li class="list-group-item">First item</li>
<li class="list-group-item">Second item</li>
<li class="list-group-item">Third item</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
Can anyone guide me how can i implement jquery on appended html by jquery, i would like to appreciate. Thank You.
Your delegate() function is fine (note that on() is now preferred, but does exactly the same thing as delegate() under the hood)
Your problem is your selector or html. You original items are inside ".list-group" but your appended items aren't, so the selector won't find them.
EDIT: The above problem is casued because .html only copies the inner html of the ul elements. To clone the actual ul's, wrap them and then take the .html of the wrapping element. This seems to work: (you could also use .clone())
$('.append-level').append(
'<div class="col-md-3 col-xs-12 col-sm-6">'+
'<h2>Child List Group</h2>'+
$(this).parent().children('ul').wrap('<div/>').html()+
'</div>');
I have done coding the first part HTML then JavaScript/JQuery. Now I want to surround the final common list with a UL need to be done using JavaScript/JQuery. So the final common list will be surrounded by two UL instead of one. Eg
Final Outcome
<ul id="CommonLister">
<ul> <!--Need to add this-->
<li class="columnItem">John</li>
<li class="columnItem">Mark</li>
</ul><!--Need to add this-->
</ul>
Current Code
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<ul id="listOne">
<li class="columnItem">John</li><!--will be removed and put under CommonLister-->
<li class="columnItem">James</li>
<li class="columnItem">Mary</li><!--will be removed and put under CommonLister-->
</ul>
<ul id="listTwo">
<li class="columnItem">John</li><!--will be removed and put under CommonLister-->
<li class="columnItem">Mark</li>
<li class="columnItem">Mary</li><!--will be removed and put under CommonLister-->
</ul>
<ul id="CommonLister">
<li class="columnItem">John</li>
<li class="columnItem">Mark</li>
</ul>
</div>
$(function() {
$('#run-code').on('click', function(e) {
e.preventDefault();
//What were you doing? nope.
var currentItems = {}; //Blank object
var $mergeColumn = $('#CommonLister'); //Common list reference
$('.columnItem').each(function(i, el) {
var $el = $(el); //Notation I use to differentiate between the regular HTML Element and jQuery element
if (!currentItems.hasOwnProperty($el.html())) {
//Has this name come up before? if not, create it.
currentItems[$el.html()] = []; //Make it equal to a brand spanking new array
}
currentItems[$el.html()].push(el);
//Add the item to the array
});
$.each(currentItems, function(name, data) {
//Loop through each name. We don't actually use the name variable because we don't care what someone's name is
if (data.length > 1) {
//Do we have more than 1 element in our array? time to move some stuff
$.each(data, function(i, el) {
var $el = $(el); //See note above
if (i == 0) {
//If this is the first element, let's just go ahead and move it to the merge column ul
$el.appendTo($mergeColumn);
} else {
$el.remove(); //Otherwise, we've already got this element so delete this one.
} //end if/else
}); //end $.each(data)
} //end if data.length >1
}); //end $.each(currentItems)
}); //end $.on()
}); //end $(
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="run-code" class="btn btn-success">Click Me</button>
<h4>List 1</h4>
<ul id="listOne">
<li class="columnItem">John</li>
<!--will be removed and put under CommonLister-->
<li class="columnItem">James</li>
<li class="columnItem">Mary</li>
<!--will be removed and put under CommonLister-->
</ul>
<h4>List 2</h4>
<ul id="listTwo">
<li class="columnItem">John</li>
<!--will be removed and put under CommonLister-->
<li class="columnItem">Mark</li>
<li class="columnItem">Mary</li>
<!--will be removed and put under CommonLister-->
</ul>
<h4>Common List</h4>
<ul id="CommonLister">
<!--Extra ul will be added here-->
</ul>
It's invalid nesting a ul directly in a ul like this but if you have to, you could use jquery wrapAll:
$( "li" ).wrapAll( "<ul></ul>" );
See fiddle: https://jsfiddle.net/9xLt6d9f/
I agree with charlietfl that it seems strange to do it this way. However, to answer your question, the best way to force this improperly formatted HTML code would be hardcode it into your original file. Try the following code for the end of your file:
<h4>Common List</h4>
<ul id="CommonLister">
<ul id="CommonListerSub">
<!--Extra ul will be added here-->
</ul>
</ul>
Then, simply change one line of your code:
var $mergeColumn = $('#CommonListerSub'); //Common list reference
This will force it to list the list items under the nested ul tags.
I hope this is an acceptable solution. If for some reason it doesn't work, please comment as to what additional limitations you have, and perhaps share the link of the page that is giving you the required template or format specifications.
I'm creating a portfolio site, and I'm struggling to select the proper elements with JQuery. My goal is to show/hide the .inner (Task) items when clicking the .outer (Category) items. I have .arrows that rotate when the menu is expanded.
This is a similar question, and the accompanying jsfiddle.
Thanks to Tats_innit for the original answer.
I have this HTML:
<li class="outer" hook="01">
<div class="arrow"></div>
Category 1
</li>
<li class="inner" id="menu-01">
Task 1
</li>
<li class="inner" id="menu-01">
Task 2
</li>
<li class="inner" id="menu-01">
Task 3
</li>
<li class="outer" hook="02">
<div class="arrow"></div>
Category 2
</li>
<li class="inner" id="menu-02">
Task 1
</li>
<li class="inner" id="menu-02">
Task 2
</li>
<li class="inner" id="menu-02">
Task 3
</li>
And this jquery:
$(document).ready(function(){
$('.outer').click(function(){
var elem = $('#menu-'+$(this).attr('hook')),
arrow = $(this).children('.arrow')
if (!elem.is(':visible')) {
arrow.rotate({animateTo:90, duration:128});
} else {
arrow.rotate({animateTo:0, duration:128});
}
elem.slideToggle('128ms', function() {
});
return false;
});
});
I understand that I need to change var elem = $('#menu-'+$(this).attr('hook')) but I'm not sure how to display all instances of .inner.
I didn't nest the .inner elements because I have a hover state background-color: #f1f1f1; for the .outer class.
This problem can be solved, but there are many things wrong with your approach in the first place, so I would like to aim to change those, instead. And then solve the problem.
The id attribute is unique. You cannot have multiple elements with the same id in the same page; for that reason, use class.
hook is not a valid HTML attribute; while it is true that this won't hurt you and browsers will most likely ignore it, I would rather see it standardized as data-hook if you so wish. This will allow you also to use the standard APIs.
You should nest the .inner inside the .outer because it makes sense semantically and it will degrade gracefully and be understandable to screen readers as well. The problem you mention about the background on hover, I think could be easily solved with some good CSS: though I didn't understand the specific issue, so I cannot say.
But fact is, that using nesting you probably don't need most of those ids, classes and random data attributes (unless obviously you need them for something else than just opening up a list).
After that you HTML will look like this:
<ul>
<li class="outer">
<div class="arrow"></div>
Category 1
<ul>
<li>
Task 1
</li>
<li>
Task 2
</li>
<li>
Task 3
</li>
</ul>
</li>
<li class="outer">
<div class="arrow"></div>
Category 1
<ul>
<li>
Task 1
</li>
<li>
Task 2
</li>
<li>
Task 3
</li>
</ul>
</li>
</ul>
And you jQuery like so:
$('.outer').click(function(){
var elem = $(this).children('ul'),
arrow = $(this).children('.arrow')
if (!elem.is(':visible')) {
arrow.rotate({animateTo:90, duration:128});
} else {
arrow.rotate({animateTo:0, duration:128});
}
elem.slideToggle('128ms', function() {
});
return false;
});
As a final note, .arrow is not a very semantic element, since it's not even used to activate the animation (the click is bound the the li.outer) I would remove it altogether and instead achieve the same effect using a pseudo-element on the said li, and perhaps rotate it with CSS3.
Edit
I am not sure why you were not able to make it function properly; though you tell me that you appreciated the comment regarding the nesting, your fiddle didn't use the correct nesting.
In any case, I put up an example for you with the advice I gave you here, and basically I just copied the code verbatim as I wrote it here. I made a few adjustments, though: such as implementing the CSS pseudoelement and getting rid of that div.arrow element, which honestly looked bad.
Obviously is just an example, but it shows how think this problem should be approached. Hopefully it will solve your doubts:
Working example
You can nest a set of outer and inner into a div
<div>
<li class="outer">
<div class="arrow"></div>
Category 1
</li>
<li class="inner">
Task 1
</li>
<li class="inner">
Task 2
</li>
<li class="inner">
Task 3
</li>
</div>
then your js code goes like
$('.outer').click(function(){
var elem = $(this).siblings('.inner'),
arrow = $(this).children('.arrow')
if (!elem.is(':visible')) {
arrow.rotate({animateTo:90, duration:128});
} else {
arrow.rotate({animateTo:0, duration:128});
}
elem.slideToggle('128ms', function() {
});
return false;
});
won't affect your background-color for outer class in the meantime
<script>
$(document).ready(function(){
$('li.inner').hide();
$('.outer').click(function()
{
var elem = $(this).attr('hook');
$('li.inner').hide();
$(".menu-"+elem).toggle();
});
});
</script>
<ul>
<li class="outer" hook="01">
<div class="arrow"></div>
Category 1
</li>
<li class="inner menu-01">
Task 1
</li>
<li class="inner menu-01">
Task 2
</li>
<li class="inner menu-01">
Task 3
</li>
<li class="outer" hook="02">
<div class="arrow"></div>
Category 2
</li>
<li class="inner menu-02">
Task 1
</li>
<li class="inner menu-02">
Task 2
</li>
<li class="inner menu-02">
Task 3
</li>
</ul>
first of all change li id to class because 2 li don't have same id
I guess you are looking for nextUntil()
$(this).nextUntil('.outer').slideToggle('218ms');
http://jsfiddle.net/bf7Ke/53/
I' trying to create a <ul> with <li> objects to slide the UL away and show specific div's.
I have these div-tags:
<div id="1"></div>
<div id="2"></div>
<div id="3"></div>
And this list:
<ul class="meny">
<li id="show1">Show 1</li>
<li id="show2">Show 2</li>
<li id="show3">Show 3</li>
</ul>
Why doesn't this JS work?
$(function() {
$("#show1").click(function() {
$(".meny" ).toggle("slide");
$("#1").click("show");
});
});
I've been trying all night long...
EDIT
I'm trying to get my project to have a CLICK-event fired when you press a specific list object. When that is done, the whole ul should slide away and show a specified div.
See: http://aatw.se/test/booking.html
it should work too-
$("#1").css("display","block");
$("#1").click("show");
should be:
$("#1").show();
Firstly your div's are empty .
Next
$("#1").click("show");
Supposed to be
$("#1").show();
You can write up a single event handler to all the li's by using HTML-5 data attributes
HTML
<div id="1">This is Div 1</div>
<div id="2">This is Div 2</div>
<div id="3">This is Div 3</div>
<ul class="meny">
<li data-id="1">Show 1</li>
<li data-id="2">Show 2</li>
<li data-id="3">Show 3</li>
</ul>
JS
$(function() {
$("li").click(function() {
$(".meny" ).toggle("slide");
$("#" + $(this).data('id')).show();
});
});
Check Fiddle
as mentioned, you need to call the show function. Your divs being empty is not an issue. But you should hide them on page load, or set them display to none in your css.
here is a fiddle - http://jsfiddle.net/D6qUe/2
here's your updated code
$("#show1").click(function() {
$(".meny" ).toggle("slide");
$("#1").show();
});
$('div').click(function(){
$('.meny').toggle('slide');
$(this).hide();
});
possible css
div{width:100px;height:100px;background-color:#afa;border:1px solid #0f0;display:none;}
Im working on html form and I have used dynatree for select and multi-select as per requirement of the project. What I need to do is to make a edit form where user gets all the fields filled from database. Which means i need to show a user a dynatree with already selected fields. Here is my example code :
<span id="action" name="action">
<ul>
<li id="DisruptiveAction" class="folder expanded">DisruptiveAction (5)
<ul>
<li id="allow" title="optional">allow
<li id="deny" title="optional">deny
<li id="pass" title="optional" class="selected" >pass
<li id="block" title="optional">block
<li id="redirect" title="optional">redirect
</ul>
</ul>
</span>
Java script :
$("#action").dynatree({
classNames: {
container: "action-container",
checkbox: "dynatree-radio"
},
selectMode: 3,
onSelect: function(select, node) {
var selKeys = $.map(node.tree.getSelectedNodes(), function(node){
return node.data.key;
});
$("#selectedAction").val(selKeys.join(","));
var selRootNodes = node.tree.getSelectedNodes(true);
var selRootKeys = $.map(selRootNodes, function(node){
return node.data.key;
});
}
});
In above mentioned html even though Im using class = "selected" with an li element but its still not showing it as selected on UI. Thanks in advance.
Dynatree creates its own elements when initializing, and throughout the lifetime of the tree. Therefore, the li elements that you are adding are not the li elements of the tree.
Take a look at this documentation, under the section "Node Options". You'll see that you can add a class like so:
<div id="tree">
<ul>
<li id="DisruptiveAction" class="folder expanded">DisruptiveAction (5)
<ul>
<li id="allow" title="optional">allow
<li id="deny" title="optional">deny
<li id="pass" title="optional" data="addClass: 'dynatree-selected'" >pass
<li id="block" title="optional">block
<li id="redirect" title="optional">redirect
</ul>
That is generic code for adding a class. There might a more specific way of specifying that an element is selected, as it is a core dynatree concept, rather than a user-defined class.