jQuery sortable - Bind new on('dblclick') to cloned element - javascript

I have connected lists using jQuery sortable().
The lists are initialized with
$( "#held, #notheld" ).sortable({
connectWith: ".connectedSortable",
}).disableSelection();
When the page loads I also bind dblclick
$('#held li').on('dblclick', function() {
var litem = $(this).clone();
litem.appendTo($('#notheld'));
$(this).remove();
update_holding(litem.attr('id'), 'remove');
$( "#held, #notheld" ).sortable( "refresh" );
});
$('#notheld li').on('dblclick', function() {
var litem = $(this).clone();
litem.appendTo($('#held'));
$(this).remove();
update_holding(litem.attr('id'), 'add');
$( "#held, #notheld" ).sortable( "refresh" );
});
Once the cloned LI is appended to the other list it needs to have the correct .on('dblclick') function bound. If I clone with true boolean as an arg the bindings get copied but I do not want the original function but rather the one associated with the list to which it now belongs.
The elements can still be dragged to new list without error.
I have tried adding the binding function to the activate, change, and update events in the initializing call in the hope that refresh() would see new element and do the .on() assignment but these were ineffective.
I also tried re-writing the initial bindings like so
$('#notheld li').on('dblclick', function() {
var litem = $(this).clone();
litem.appendTo($('#held'));
$(this).remove();
update_holding(litem.attr('id'), 'add');
litem.on('dblclick', function() {
var litem2 = $(this).clone();
litem2.appendTo($('#notheld'));
$(this).remove();
update_holding(litem2.attr('id'), 'remove');
});
});
But this does not call the function correctly? Perhaps the use of $(this) is not correct?
The update_holding() function should not bear on the issue as it is just an ajax post to another script managing the database updates.
Here is a working example: https://jsfiddle.net/qn6v42c9/
Also read
jQuery clone() not cloning event bindings, even with on() and
jquery .on() doesn't work for cloned element

I would use click event delegation on sortable container itself so I would not have to bind the dbclick again and again, here is the code for it
$("#held, #notheld").sortable({
connectWith: ".connectedSortable",
}).disableSelection();
$('#held').on('dblclick', 'li', function() {
var litem = $(this).clone();
litem.appendTo($('#notheld'));
$(this).remove();
update_holding(litem.attr('id'), 'remove');
$("#held, #notheld").sortable("refresh");
});
$('#notheld').on('dblclick', 'li', function() {
var litem = $(this).clone();
litem.appendTo($('#held'));
$(this).remove();
update_holding(litem.attr('id'), 'add');
$("#held, #notheld").sortable("refresh");
});
// dropped
$('#held').on('sortreceive', function(event, ui) {
update_holding(ui.item.attr('id'), 'add');
});
// dropped
$('#notheld').on('sortreceive', function(event, ui) {
update_holding(ui.item.attr('id'), 'remove');
});
function update_holding(EntityNumber, action) {
// ajax here
}
#held, #notheld {
border: 1px solid #eee;
width: 272px;
min-height: 20px;
list-style-type: none;
margin: 0;
padding: 5px 0 0 0;
float: left;
margin-right: 10px;
}
#held li, #notheld li {
margin: 0 5px 5px 5px;
padding: 5px;
font-size: 1.2em;
width: 250px;
cursor:move;
}
#notheld li {
float: left;
clear: none;
display: inline-block;
}
div#notheld-container, div#held-container {
width: 300px;
float:left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet"/>
<div id="notheld-container">
<h3>Properties Not Held by <em>Client</em></h3>
<ul id="notheld" class="connectedSortable">
</ul>
</div>
<div id="held-container">
<h3>Current Holdings</h3>
<ul id="held" class="connectedSortable ui-sortable">
<li class="ui-state-highlight ui-sortable-handle" id="12">Farragut (12)</li><li class="ui-state-highlight ui-sortable-handle" id="1010" style="">King Street (1010)</li>
<li class="ui-state-highlight ui-sortable-handle" id="07">Annandale (07)</li>
<li class="ui-state-highlight ui-sortable-handle" id="13">Aquahart (13)</li>
</ul>
</div>

Related

Drag and Drop multiple files using JqueryUI

I struggle with the following problem
I have a Page where a user can drag and drop files into another DIV. The user now wants to Drag and Drop multiple files with one drag. The problem however is, I found a codesnippet online (cant find it anymore sadly), customised the code to meet the design requests and now I'm stuck with enabling that multifile Drag and Drop.
I'm a complete beginner if it comes to JqueryUI.
The idea is to add checkboxes in the corners of the files/pictures. All selected items should be moved at once with a Drag and Drop.
Idealy the user should be able to mark the necessary file with the mouse Drag and Drop, but that's just nice to have and not a crucial requirement.
I don't want to ask fora complete solution from someone, but rather for possible sources or examples where i can try and create a personal custom solution from.
CODE:
HTML:
<ul class="gallery col-md-8 borderBoxes" id="gallery">
#foreach (var item in Model.PageList)
{
<li class="imageListItem ui-icon-zoomin" id="#item.ID">
<img class="pages small" src="data:image/jpeg;base64,#item.ImageBaase64" onclick="imageLarger(this)" />
</li>
}
</ul>
<div id="trash" class="col-md-3">
</div>
<div id="documentContainer" class="document-container">
<div class="row justify-content-between">
<button id="addNewDocument" class="col-2 btn btn-primary add-doc-button">new document</button>
<form method="post" class="col-md-2 offset-md-10 forward-form">
</form>
</div>
<ul id="newDocuments"></ul>
</div>
<div style="display: none;">
<div id="docDescription" class='col-md-4 form-group documentDescription'>
<label class='control-label input-label'>Dokumenttyp</label>
<select>
<!--stuff that is not important for this post-->
</select>
</div>
</div>
JavaScript:
function imageLarger(image, liID) {
if ($(image).width() === 700) {
$(image).width(100);
setTimeout(function () {
$(image).removeClass("largePages");
}, 300);
} else {
$(image).width(700);
$(image).addClass("largePages");
}
};
$("#addNewDocument").click(function () {
var uid = Math.floor(Math.random() * 26) + Date.now()
var newDocumentBox = $("<li class='row documentContainer justify-content-between' id='" + uid + "'></li>").prependTo("#newDocuments");
var newDocumentDescription = $("#docDescription").clone(true);
newDocumentDescription.appendTo(newDocumentBox);
var newDroppableBox = $("<div class='documents col-md-7 droppableBox' ></div>").appendTo(newDocumentBox);
var newDeleteButton = $("<div class='close-container deleteButton' onclick='deleteDocument(" + uid + ")'><div class='leftright'></div><div class='rightleft'></div></div>").appendTo(newDroppableBox);
newDroppableBox.droppable({
accept: "#gallery > li",
drop: function (event, ui) {
ui.draggable.appendTo(this).fadeIn(function () {
ui.draggable
.animate()
.find("img")
});
}
});
});
function deleteDocument(elementID) {
var element = document.getElementById(elementID);
var listOfPages = element.getElementsByClassName("imageListItem");
var amounOfPages = listOfPages.length;
if (element.style.display !== "none") {
element.style.display = "none";
for (var i = 0; i < amounOfPages; i++) {
$("#gallery").append(listOfPages[0]); // 0 because removing an object decreases $children.length by 1
}
}
};
$(function () {
var $gallery = $("#gallery"),
$trash = $("#trash"),
$document = $("#document"),
trash_icon = "<a href='link/to/trash/script/when/we/have/js/off' title='Delete this image' class='ui-icon ui-icon-trash'>Delete image</a>",
recycle_icon = "<a href='link/to/recycle/script/when/we/have/js/off' title='Recycle this image' class='ui-icon ui-icon-refresh'>Recycle image</a>";
$("li", $gallery)
.draggable({
cancel: "a.ui-icon",
revert: "invalid",
containment: "document",
helper: "clone",
cursor: "move"
});
$trash
.droppable({
accept: "li",
drop: function (event, ui) {
deleteImage(ui.draggable);
}
});
$gallery
.droppable({
accept: "li",
drop: function (event, ui) {
recycleImage(ui.draggable);
}
});
$document
.droppable({
accept: "li",
drop: function (event, ui) {
ui.draggable.appendTo(this).fadeIn(function () {
$item
.animate()
.find("img")
});
deleteImage(ui.draggable);
}
});
function deleteImage($item) {
$item.fadeOut(function () {
var $list = $("ul", $trash).length ?
$("ul", $trash) :
$("<ul class='gallery ui-helper-reset'/>").appendTo($trash);
$item.find("a.ui-icon-trash").remove();
$item.append(recycle_icon).appendTo($list).fadeIn(function () {
$item.addClass('removedPage');
$item
.animate()
.find("img")
});
});
}
function recycleImage($item) {
$item.fadeOut(function () {
$item.removeClass('removedPage');
$item
.find("a.ui-icon-refresh")
.remove()
.end()
.find("img")
.end()
.appendTo($gallery)
.fadeIn();
});
}
$("#recycleAllDocuments")
.on("click", function () {
if ($('#trash').children().length > 0) {
var listOfDeletedItems = document.getElementById("trash").getElementsByClassName("imageListItem");
for (var i = 0; i < listOfDeletedItems.length; i++) {
var $item = $(listOfDeletedItems[i]);
recycleImage($item);
}
}
});
$("deleteButton")
.on("click", function () {
var $item = $(this);
recycleImages($item);
});
$("ul.gallery > li")
.on("click", function (event) {
var $item = $(this),
$target = $(event.target);
if ($target.is("a.ui-icon-trash")) {
deleteImage($item);
} else if ($target.is("a.ui-icon-zoomin")) {
viewLargerImage($target);
} else if ($target.is("a.ui-icon-refresh")) {
recycleImage($item);
}
return false;
});
});
Consider the following example.
$(function() {
var $gallery = $("#gallery"),
$trash = $("#trash"),
$document = $("#document"),
trash_icon = "<a href='link/to/trash/script/when/we/have/js/off' title='Delete this image' class='ui-icon ui-icon-trash'>Delete image</a>",
recycle_icon = "<a href='link/to/recycle/script/when/we/have/js/off' title='Recycle this image' class='ui-icon ui-icon-refresh'>Recycle image</a>";
$("li", $gallery)
.draggable({
cancel: "a.ui-icon",
revert: "invalid",
containment: "document",
helper: function() {
var help = $("<div>", {
class: "ui-draggable-helper"
});
if ($(".ui-selected").length) {
help.data("items", $(".ui-selected"));
help.addClass("multiple");
} else {
help.data("items", $(this));
}
return help;
},
cursor: "move"
});
$gallery.selectable();
$trash
.droppable({
accept: "li",
drop: function(event, ui) {
deleteImage(ui.helper.data("items"));
}
});
$gallery
.droppable({
accept: "li",
drop: function(event, ui) {
recycleImage(ui.draggable);
}
});
$document
.droppable({
accept: "li",
drop: function(event, ui) {
ui.draggable.appendTo(this).fadeIn(function() {
$item
.animate()
.find("img")
});
deleteImage(ui.draggable);
}
});
function deleteImage($item) {
$item.fadeOut(function() {
var $list = $("ul", $trash).length ?
$("ul", $trash) :
$("<ul class='gallery ui-helper-reset'/>").appendTo($trash);
$item.find("a.ui-icon-trash").remove();
$item.append(recycle_icon).appendTo($list).removeClass("ui-selected").fadeIn(function() {
$item.addClass('removedPage');
$item
.animate()
.find("img")
});
});
}
function recycleImage($item) {
$item.fadeOut(function() {
$item.removeClass('removedPage');
$item
.find("a.ui-icon-refresh")
.remove()
.end()
.find("img")
.end()
.appendTo($gallery)
.fadeIn();
});
}
$("#recycleAllDocuments")
.on("click", function() {
if ($('#trash').children().length > 0) {
var listOfDeletedItems = document.getElementById("trash").getElementsByClassName("imageListItem");
for (var i = 0; i < listOfDeletedItems.length; i++) {
var $item = $(listOfDeletedItems[i]);
recycleImage($item);
}
}
});
$("deleteButton")
.on("click", function() {
var $item = $(this);
recycleImages($item);
});
$("ul.gallery > li")
.on("click", function(event) {
var $item = $(this),
$target = $(event.target);
if ($target.is("a.ui-icon-trash")) {
deleteImage($item);
} else if ($target.is("a.ui-icon-zoomin")) {
viewLargerImage($target);
} else if ($target.is("a.ui-icon-refresh")) {
recycleImage($item);
}
return false;
});
});
.gallery {
list-style: none;
}
.gallery .ui-selecting {
background: #ccc;
border-color: #999;
}
.gallery .ui-selected {
background: #eee;
border-color: #222
}
.imageListItem {
width: 100px;
height: 100px;
border: 1px solid #ccc;
border-radius: 3px;
display: inline-block;
margin: 3px;
}
.ui-draggable-helper {
background: #fff;
width: 50px;
height: 65px;
border: 1px solid #999;
border-radius: 3px;
position: relative;
z-index: 100;
}
.ui-draggable-helper:after {
content: "";
width: 0;
height: 0;
border-bottom: 20px solid #999;
border-right: 20px solid #fff;
position: absolute;
left: 29px;
top: -1px;
}
.ui-draggable-helper.multiple:before {
content: "";
width: 50px;
height: 65px;
border-left: 1px solid #999;
border-bottom: 1px solid #999;
border-radius: 3px;
position: absolute;
top: 5px;
left: -5px;
z-index: 0;
}
#trash {
border: 1px solid #ccc;
width: 200px;
height: 200px;
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<ul class="gallery col-md-8 borderBoxes" id="gallery">
<li class="imageListItem ui-icon-zoomin" id="item-1">
<img class="pages small" src="data:image/jpeg;base64,#item.ImageBaase64" onclick="imageLarger(this)" />
</li>
<li class="imageListItem ui-icon-zoomin" id="item-2">
<img class="pages small" src="data:image/jpeg;base64,#item.ImageBaase64" onclick="imageLarger(this)" />
</li>
<li class="imageListItem ui-icon-zoomin" id="item-3">
<img class="pages small" src="data:image/jpeg;base64,#item.ImageBaase64" onclick="imageLarger(this)" />
</li>
</ul>
<div id="trash" class="col-md-3">
</div>
<div id="documentContainer" class="document-container">
<div class="row justify-content-between">
<button id="addNewDocument" class="col-2 btn btn-primary add-doc-button">new document</button>
<form method="post" class="col-md-2 offset-md-10 forward-form">
</form>
</div>
<ul id="newDocuments"></ul>
</div>
<div style="display: none;">
<div id="docDescription" class='col-md-4 form-group documentDescription'>
<label class='control-label input-label'>Dokumenttyp</label>
<select>
<!--stuff that is not important for this post-->
</select>
</div>
</div>
With Draggable, you can create your own helper with a Function call.
Allows for a helper element to be used for dragging display. Multiple types supported:
String: If set to "clone", then the element will be cloned and the clone will be dragged.
Function: A function that will return a DOMElement to use while dragging.
So if you want to represent multiple items, you can make a helper looks like this and you can use .data() to carry all the items. When you drop the helper, you can then perform the actions needed on each of the items.
Making use of Selectable, the User can select a number of items in the gallery and then drag them to the Trash, in this example.

make a dropped div, droppable again

I am trying to make an editor of a sort were you choose your layout for the given section and then drop another paragraph, button, img etc. on to the content area of that layout.
The thing is that when ever i drop the first div "layout" and i try to drop an item to that div, it chooses the wrong droppable area, because it is located "behind" the, as if the z-index is wrong, but the correct area is visible.
i made i jsfiddle as an example of the code, I'am logging the id of the droppable area and the dropped item in the console:
https://jsfiddle.net/g9aragsp/3/
so i would to add one of the "items" to the "insidedrop" instead of the "editor". Ive only set the id "insidedrop" on the first layout for testing purpose.
My html:
<div class="container-fluid">
<div class="row content">
<div class="col-sm-8 col-sm-offset-2">
<div class="row htmlEditor">
<div class="col-sm-3" style="background-color: gray; min-height: 800px;">
<p style="border-bottom: 5px solid black">Layouts</p>
<ul id="layouts" style="list-style-type: none;">
<li id="layout1" class="PickerButton">layout1</li>
<li id="layout2" class="PickerButton">layout2</li>
<li id="layout3" class="PickerButton">layout3</li>
</ul>
<p style="border-bottom: 5px solid black">Items</p>
<ul id="items" style="list-style-type: none;">
<li id="item1" class="PickerButton">button</li>
<li id="item2" class="PickerButton">img</li>
<li id="item3" class="PickerButton">text</li>
</ul>
</div>
<div id="editor" class="col-sm-9" style="background-color: lightgray; min-height: 800px; padding: 20px;">
</div>
</div>
</div>
</div>
</div>
My Javascript:
$(function () {
var $layouts = $("#layouts"),
$items = $("#items"),
$insideDrop = $("#insideDrop"),
$trash = $("#editor");
$("li", $layouts).draggable({
cancel: "button", // these elements won't initiate dragging
revert: "invalid", // when not dropped, the item will revert back to its initial position
containment: "document",
helper: "clone",
cursor: "move"
});
$("li", $items).draggable({
cancel: "button", // these elements won't initiate dragging
revert: "invalid", // when not dropped, the item will revert back to its initial position
containment: "document",
helper: "clone",
cursor: "move"
});
$trash.droppable({
//accept: "#list1 > li",
drop: function (event, ui) {
console.log(ui.draggable.attr("id"));
console.log($(this).attr("id"));
if (ui.draggable.attr("id") == "layout1")
$("#editor").append("<div class='layout1Outer' style='min-height:400px; margin-bottom: 15px;'><div class='layout1imageplaceholder' style='background-color:#8a2be2;height:150px'></div><div class='layout1content' id='insideDrop' style='background-color:bisque;min-height:250px'></div></div>");
if (ui.draggable.attr("id") == "layout2")
$("#editor").append("<div class='layout2Outer' style='min-height:400px; margin-bottom: 15px;'><div class='layout2imageplaceholder' style='background-color:#8a2be2;float:right;height:400px;width:40%'></div><div class='layout2content' style='background-color:bisque;float:left;min-height:400px;width:60%'></div></div>");
if (ui.draggable.attr("id") == "layout3")
$("#editor").append("<div class='layout3Outer' style='min-height:400px; margin-bottom: 15px;'><div class='layout3imageplaceholder' style='background-color:#8a2be2;float:left;height:400px;width:40%'></div><div class='layout3content' style='background-color:bisque;float:right;min-height:400px;width:60%'></div></div>");
}
});
$insideDrop.droppable({
drop: function (event, ui) {
if (ui.draggable.attr("id") == "item1")
$("#insideDrop").append("<span id='button' style='background-color:#dc143c;padding: 10px; width: 50px'>BUTTON</span>");
if (ui.draggable.attr("id") == "item2")
$("#insideDrop").append("<img src='http://via.placeholder.com/50x50'>");
if (ui.draggable.attr("id") == "item3")
$("#insideDrop").append("<p style='background- color: #284B63; padding: 10px; width: 200px; color: white;'>Insert text here</p>");
console.log(ui.draggable.attr("id"));
}
});
});
I figured out a solution to the problem. instead of targeting a nested "droppable" container. i reused the same function and on hover made javascript return the current hovered object, and then append the item to that specific object as so:
var hoveredObj;
function getid(obj) {
hoveredObj = obj;
}
var $layouts = $("#layouts"),
$items = $("#items"),
$insideDrop = $("#insideDrop"),
$editor = $("#editor");
$("li", $layouts).draggable({
cancel: "button", // these elements won't initiate dragging
revert: "invalid", // when not dropped, the item will revert back to its initial position
containment: "document",
helper: "clone",
cursor: "move"
});
$("li", $items).draggable({
cancel: "button", // these elements won't initiate dragging
revert: "invalid", // when not dropped, the item will revert back to its initial position
containment: "document",
helper: "clone",
cursor: "move"
});
$editor.droppable({
//accept: "#list1 > li",
drop: function (event, ui) {
console.log(ui.draggable.attr("id"));
console.log($(this).attr("id"));
if (ui.draggable.attr("id") == "layout1")
$("#editor").append("<div class='layout1Outer' style='min-height:400px; margin-bottom: 15px;'><div class='layout1imageplaceholder' style='background-color:#8a2be2;height:150px'></div><div class='layout1content' id='insideDrop' onmouseover='getid(this)' style='background-color:bisque;min-height:250px'></div></div>");
if (ui.draggable.attr("id") == "layout2")
$("#editor").append("<div class='layout3Outer' style='min-height:400px; margin-bottom: 15px;'><div class='layout3imageplaceholder' style='background-color:#8a2be2;float:left;height:400px;width:40%'></div><div class='layout3content' style='background-color:bisque;float:right;min-height:400px;width:60%'></div></div>");
if (ui.draggable.attr("id") == "layout3")
$("#editor").append("<div class='layout2Outer' style='min-height:400px; margin-bottom: 15px;'><div class='layout2imageplaceholder' style='background-color:#8a2be2;float:right;height:400px;width:40%'></div><div class='layout2content' style='background-color:bisque;float:left;min-height:400px;width:60%'></div></div>");
if (ui.draggable.attr("id") == "item1")
$(hoveredObj).append("<span id='button' style='background-color:#dc143c;padding: 10px; width: 50px'>BUTTON</span>");
if (ui.draggable.attr("id") == "item2")
$(hoveredObj).append("<img src='http://via.placeholder.com/50x50'>");
if (ui.draggable.attr("id") == "item3")
$(hoveredObj).append("<p style='background- color: #284B63; padding: 10px; width: 200px; color: white;'>Insert text here</p>");
}
});

How to activate menu tab after refreshing

How can I activate a menu tab after refreshing?
Here are my code
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<style>
.menu{width: 600px; height: 25; font-size: 18px;}
.menu li{list-style: none; float: left; margin-right: 4px; padding: 5px;}
.menu li:hover, .menu li.active {
background-color: #f90;
}
</style>
</head>
<body>
<ul class="menu">
<li><a href='#'>One</a></li>
<li><a href='#'>Two</a></li>
<li><a href='#'>Three</a></li>
<li><a href='#'>Four</a></li>
</ul>
<script type="text/javascript">
var make_button_active = function()
{
//Get item siblings
var siblings =($(this).siblings());
//Remove active class on all buttons
siblings.each(function (index)
{
$(this).removeClass('active');
}
)
//Add the clicked button class
$(this).addClass('active');
}
//Attach events to menu
$(document).ready(
function()
{
$(".menu li").click(make_button_active);
}
)
</script>
Can anyone tell me How to resolve this issue ?
Just like #Johan said, store your last active tab in a localStorage or cookie. Since there is no noticeable difference in performance between the two. I suggest you use localStorage because it's much easier to use. Like this:
function make_button_active(tab) {
//Get item siblings
var siblings = tab.siblings();
//Remove active class on all buttons
siblings.each(function(){
$(this).removeClass('active');
})
//Add the clicked button class
tab.addClass('active');
}
//Attach events to menu
$(document).ready(function(){
if(localStorage){
var ind = localStorage['tab']
make_button_active($('.menu li').eq(ind));
}
$(".menu li").click(function () {
if(localStorage){
localStorage['tab'] = $(this).index();
}
make_button_active($(this));
});
});
Check out this fiddle.

JQuery - select-result show message on select

plugin demo: http://jqueryui.com/selectable/#serialize
Hello, I don't quite understand this "plugin" and specifically
result.append( " #" + ( index + 1) ); &
<span>You've selected:</span> <span id="select-result">none</span>.
I want the user to be able to select one of the following "buttons" and then a message to show in place of the Number selected (as in the demo)
So: You've selected: #2.
Would be: You've selected: UK, please goto this and do that etc...
im guessing the easiest way is with JavaScript
if "select-result" = 1 then
else
Sort of thing?
Any help Would be great! i hope this isn't a stupid question...
Code:
<html>
<head>
<title>jQuery UI Selectable - Serialize</title>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.2/themes/smoothness/jquery- ui.css" />
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="http://code.jquery.com/ui/1.10.2/jquery-ui.js"></script>
<link rel="stylesheet" href="/resources/demos/style.css" />
<style>
#feedback { font-size: 1.4em; }
#selectable .ui-selecting { background: #FECA40; }
#selectable .ui-selected { background: #F39814; color: white; }
#selectable { list-style-type: none; margin: 0; padding: 0; width: 60%; }
#selectable li { margin: 3px; padding: 0.4em; font-size: 1.4em; height: 18px; }
</style>
<script>
$(function() {
$( "#selectable" ).selectable({
stop: function() {
var result = $( "#select-result" ).empty();
$( ".ui-selected", this ).each(function() {
var index = $( "#selectable li" ).index( this );
result.append( " #" + ( index + 1) );
});
}
});
});
</script>
</head>
<body>
<p id="feedback">
<span>You've selected:</span> <span id="select-result">none</span>.
</p>
<ol id="selectable">
<li class="ui-widget-content">UK</li>
<li class="ui-widget-content">USA</li>
<li class="ui-widget-content">FR</li>
<li class="ui-widget-content">AU</li>
<li class="ui-widget-content">CA</li>
<li class="ui-widget-content">DE</li>
</ol>
</body>
</html>
the example in the plugins is showing the selected index.. you don't need to do that... what you need to do is get the text of selected and show it in span.. so use.. html() or text()..
try this
$(function() {
$( "#selectable" ).selectable({
stop: function() {
var result = $( "#select-result" );
result.html($(this).html()); // result.text($(this).text());
}
});
});
var index = $( "#selectable li" ).index( this );
This grabs the index of the element we've been passed. We don't need this line.
result.append( " #" + ( index + 1) );
The index is the position at which the element occurs while descending the DOM.
We can change the above lines to one simple thing.
$( ".ui-selected", this ).text().appendTo(result);
Edit: See above, this may refer to the entire ul, so we need to filter it by the item that is selected. If you are allowing for a multi-select, then see below.
$( ".ui-selected", this ).each(function(){
$(this).text().appendTo(result);
});

How to convert unordered list into nicely styled <select> dropdown using jquery?

How do I convert an unordered list in this format
<ul class="selectdropdown">
<li>one</li>
<li>two</li>
<li>three</li>
<li>four</li>
<li>five</li>
<li>six</li>
<li>seven</li>
</ul>
into a dropdown in this format
<select>
<option value="one.html" target="_blank">one</option>
<option value="two.html" target="_blank">two</option>
<option value="three.html" target="_blank">three</option>
<option value="four.html" target="_blank">four</option>
<option value="five.html" target="_blank">five</option>
<option value="six.html" target="_blank">six</option>
<option value="seven.html" target="_blank">seven</option>
</select>
using jQuery?
Edit: When selecting an entry from the select/dropdown the link should open in a new window or tab automatically. I also want to able to style it like: http://www.dfc-e.com/metiers/multimedia/opensource/jqtransform/
$(function() {
$('ul.selectdropdown').each(function() {
var $select = $('<select />');
$(this).find('a').each(function() {
var $option = $('<option />');
$option.attr('value', $(this).attr('href')).html($(this).html());
$select.append($option);
});
$(this).replaceWith($select);
});
});
EDIT
As with any jQuery code you want to run on page load, you have to wrap it inside $(document).ready(function() { ... }); block, or inside it's shorter version $(function() { ... });. I updated the function to show this.
EDIT
There was a bug in my code also, tried to take href from the li element.
$('ul.selectdropdown').each(function() {
var select = $(document.createElement('select')).insertBefore($(this).hide());
$('>li a', this).each(function() {
var a = $(this).click(function() {
if ($(this).attr('target')==='_blank') {
window.open(this.href);
}
else {
window.location.href = this.href;
}
}),
option = $(document.createElement('option')).appendTo(select).val(this.href).html($(this).html()).click(function() {
a.click();
});
});
});
In reply to your last comment, I modified it a little bit but haven't tested it. Let me know.
$('ul.selectdropdown').each(function() {
var list = $(this), select = $(document.createElement('select')).insertBefore($(this).hide());
$('>li a', this).each(function() {
var target = $(this).attr('target'),
option = $(document.createElement('option'))
.appendTo(select)
.val(this.href)
.html($(this).html())
.click(function(){
if(target==='_blank') {
window.open($(this).val());
}
else {
window.location.href = $(this).val();
}
});
});
list.remove();
});
This solution is working also in IE and working with selected item (in anchor tag).
$('ul.selectdropdown').each(function(){
var list=$(this),
select=$(document.createElement('select')).insertBefore($(this).hide()).change(function(){
window.location.href=$(this).val();
});
$('>li a', this).each(function(){
var option=$(document.createElement('option'))
.appendTo(select)
.val(this.href)
.html($(this).html());
if($(this).attr('class') === 'selected'){
option.attr('selected','selected');
}
});
list.remove();
});
Thank you all for posting the codes. My scenario is similar but my situation is for Responsiveness that for x-size it would switch to a dropdown list, then if not x-size, using csswatch to check for the "display" properties of an element that has certain amount of width set to it (eg: 740px). Thought I share this solution for anyone who is interested. This is what I have combined with Tatu' codes. Instead of replacing the html, I created then hide the new html then only add them when necessary:
var $list = $('ul.list');
(listFunc = function(display){
//Less than x-size turns it into a dropdown list
if(display == 'block'){
$list.hide();
if($('.sels').length){
$('.sels').show();
} else {
var $select = $('<select class="sels" />');
$list.find('a').each(function() {
var $option = $('<option />');
$option.attr('value', $(this).attr('href')).html($(this).html());
$select.append($option);
});
$select.insertAfter($list);
$('.sels').on('change', function(){
window.location = this.value;
});
}
} else {
$('.sels').hide();
$list.show();
}
})(element.css('display'));
element.csswatch({
props: 'display'
}).on('css-change', function (event, change) {
return listFunc(change.display);
});
I have recently created a solution where the ul transformed, mimics nearly completely the select.
It has in adition a search for the options of the select and supports the active state. Just add a class with name active and that option will be selected.
It handles the keyboard navigation.
Take a look at the code here: GitHub Code
And a live example here: Code Example
The unordered list must be in the form:
<ul id="...">
<li>...</li>
<li>...</li>
<li><a class="active" href="...">...</a></li>
...
</ul>
To convert the ul to select just call:
$(window).on("load resize", function() {
ulToSelect($("ul#id"), 767);
});
Where #id is an id for the unordered list and 767 is the minimum width of the window for the convertion to take place. This is very useful if you want the convertion to take place only for mobile or tablet.
I found this gorgeous CodePen from #nuckecy for anyone interested:
https://codepen.io/nuckecy/pen/ErPqQm
$(".select").click(function() {
var is_open = $(this).hasClass("open");
if (is_open) {
$(this).removeClass("open");
} else {
$(this).addClass("open");
}
});
$(".select li").click(function() {
var selected_value = $(this).html();
var first_li = $(".select li:first-child").html();
$(".select li:first-child").html(selected_value);
$(this).html(first_li);
});
$(document).mouseup(function(event) {
var target = event.target;
var select = $(".select");
if (!select.is(target) && select.has(target).length === 0) {
select.removeClass("open");
}
});
His default CSS rules:
.select li {
display: none;
cursor: pointer;
padding: 5px 10px;
border-top: 1px solid black;
min-width: 150px;
}
.select li:first-child {
display: block;
border-top: 0px;
}
.select {
border: 1px solid black;
display: inline-block;
padding: 0;
border-radius: 4px;
position: relative;
}
.select li:hover {
background-color: #ddd;
}
.select li:first-child:hover {
background-color: transparent;
}
.select.open li {
display: block;
}
.select span:before {
position: absolute;
top: 5px;
right: 15px;
content: "\2193";
}
.select.open span:before {
content: "\2191";
}

Categories