jQuery drag-drop working for files, but not folders - javascript

I'm using the jquery and jquery UI plugin to drag and drop elements (folders and files) just like in a filebrowser.
I can manage to have the file go 'into' the folder, but not a folder to go into another.
Here is a demo :
There seems to be something conflicting, but I don't know where to look anymore.
The javascript is like this :
$(function () {
// fancytree is part of another script
$("#tree").fancytree({
expandLazy: true,
activate: function (event, data) {
var node = data.node;
if (node.data.href) {
window.open(node.data.href, node.data.target);
}
}
});
/* DRAG AND DROP STARTS HERE */
$(".listitems").draggable();
$(".droppable").droppable({
//preventCollision: true,
drop: function (event, ui) {
var draggableId = ui.draggable.attr("id");
var droppableId = $(this).attr("id");
//alert('FILE'+draggableId+' DROPED INTO '+droppableId);
$(this).append(ui.draggable);
var itemid = ui.draggable.attr('data-itemid');
var folderid = ui.draggable.attr('data-fldmid');
if (typeof folderid == 'undefined') {
folderid = 0;
}
if (typeof itemid == 'undefined') {
itemid = 0;
}
if (typeof droppableId == 'undefined') {
droppableId = 0;
}
$.ajax({
method: "POST",
url: "_ajax/filemanager/dragdrop.php",
//data : 'FileID='+ itemid +'&FolderID='+ droppableId,
data: 'FileID=' + itemid + '&FolderID=' + folderid + '&DropID=' + droppableId,
}).done(function (data) {
var result = $.parseJSON(data);
if (folderid == 0) {
//alert('FILE MOVED - FileID='+ itemid +'&FolderID='+ folderid+'&DropID='+ droppableId);
// Done moving file, hiding it
$("div#" + itemid).hide(500);
} else {
//alert('FOLDER MOVED - FileID='+ itemid +'&FolderID='+ folderid+'&DropID='+ droppableId);
// Done moving directory, hiding it
$("div#" + folderid).hide(500);
}
//$("div#"+folderid).hide(500);
//$("div#"+droppableId).hide(500);
});
}
});
$(".listitems").sortable();
$(".listitems").disableSelection();
var shouldCancel = false;
$('.dragMe').draggable({
containment: '.moveInHere',
revert: function () {
if (shouldCancel) {
shouldCancel = false;
return true;
} else {
return false;
}
}
});
$('.butNotHere').droppable({
over: function () {
shouldCancel = true;
},
out: function () {
shouldCancel = false;
}
});
});
And here is the html
<div class="box-body">
<div class="table-responsive mailbox-messages moveInHere" style="overflow: hidden; min-height:600px;">
<p>
<!--id, data-fldmid and data-itemid were added for testing purposes -->
<div class="boxFile small droppable listitems dragMe drag" id="D.4" data-fldmid='D.4' data-itemid='4'>
<a href="?n=9">
<div class="ffolder small yellow"></div>
</a>
<div class="boxFileTitle">Folder 1 (4)</div>
</div>
<div class="boxFile small droppable listitems dragMe drag" id="D.7" data-fldmid='D.7' data-itemid='7'>
<a href="?n=7">
<div class="ffolder small yellow"></div>
</a>
<div class="boxFileTitle">Folder A (7)</div>
</div>
<p>
<div style="" class="boxFile small listitems butNotHere dragMe drag" id="26" data-itemid='26'>
<img src='image.php?id=26' class='UploadedImageThumb'>
<div class="boxFileTitle">2016-12-12 14.50.14.jpg26</div>
<div class="boxFileOption">Preview | Edit | Trash</div>
</div>
</p>
<p>
<div style="" class="boxFile small listitems butNotHere dragMe drag" id="25" data-itemid='25'>
<img src='image.php?id=25' class='UploadedImageThumb'>
<div class="boxFileTitle">test.jpg25</div>
<div class="boxFileOption">Preview | Edit | Trash</div>
</div>
</p>
</p>
</div>
</div>
The 'butNotHere' class is to prevent files to be on top of each other. All this works fine, except the folder-into-folder dragging as described above.

I found the error, the variable in JS (folderid) had a letter 'D' in front of the real id. I did this during test to check if it was a file being moved or folder. So 'F' or 'D'.
So I changed this line
data-fldmid='D.7'
To this and it worked
data-fldmid='7'

Related

How can I create Nested Treeview in Mvc5 View with Ajax and JS approach

I have a simple MVC view which the department name. There is a hierarchy on the department which I use in the nested Treeview node.
My current approach shows the TREEVIEW but only stops by 1 nested.
I want to display all the existing department hierarchy in the Treeview. Something like the figure below:
> Galaxy Department
|
|___> Moon Department
|
|____> Starts Department
|
|___> Cloud department
|
|___> And so on....
My mvc View:
<div class="col-md-3" style="border:1px solid black; height:725px; background-color:#FAFAFA">
<span style="font-weight:500;">Triple4</span>
#{
<div class="treeview">
#{
if (Model != null && Model.Count() > 0)
{
<ul>
#foreach (var i in Model)
{
<li>
<span class="collapse collapsible" data-loaded="false" pid="#i.DepartId"> </span>
<span>
#i.DepatName
</span>
</li>
}
</ul>
}
}
</div>
}
</div>
My Ajax :
$(".collapsible").on("click", function (e) {
e.preventDefault();
var this1 = $(this); // Get Click item
var data = {
pid: $(this).attr('pid')
};
var isLoaded = $(this1).attr('data-loaded'); // Check data already loaded or not
if (isLoaded == "false") {
$(this1).addClass("loadingP"); // Show loading panel
$(this1).removeClass("collapse");
// Now Load Data Part1
$.ajax({
url: "/Department/GetTreeViewList/",
type: "GET",
data: data,
dataType: "json",
success: function (d) {
$(this1).removeClass("loadingP");
if (d.length > 0) {
var $ul = $("<ul></ul>");
//var result;
$.each(d, function (i, ele) {
$ul.append(
$("<li></li>").append(
"<span class='collapse collapsible' data-loaded='false' pid='" + ele.DepartId + "'> </span>" +
"<span><a href='" + ele.NavUrl + "' id='directavail' >" + ele.DepatName + "</a></span>"
)
)
});
//$("[data-role=collapsible]").trigger("collapse");
$(this1).parent().append($ul);
$(this1).addClass('collapse');
$(this1).toggleClass('collapse expand');
$(this1).closest('li').children('ul').slideDown();
}
else {
// no sub menu
$(this1).css({ 'dispaly': 'inline-block', 'width': '15px' });
}
$(this1).attr('data-loaded', true);
},
error: function () {
alert("Error!");
}
});
}
else {
// if already data loaded
$(this1).toggleClass("collapse expand");
$(this1).closest('li').children('ul').slideToggle();
}
});
Any Subjection is very welcome.
I have found a very good approach from #Sourav Mondal
TreeView on Demand
Very quick and Accurate approach which I had to some changes on a JS script since it's old.
And the link it's just a tutorial and guideline.
Hopefully, it's helping someone too.

how to move selected item in a list using up and down arrow keys in javascript?

I am trying to implement up and down arrow buttons for a list in HTML. the up arrow moves the selected element of list upwards and the down arrow moves the selected list element downwards. I tried this code, but not working ::
function reorder_up(node) {
$(".go_up").click(function() {
var $current = $(this).closest('li')
var $previous = $current.prev('li');
if ($previous.length !== 0) {
$current.insertBefore($previous);
}
return false;
});
}
function reorder_down(node) {
$(".go_down").click(function() {
var $current = $(this).closest('li')
var $next = $current.next('li');
if ($next.length !== 0) {
$current.insertAfter($next);
}
return false;
});
}
// for adding to the result page i am using this function, where i am creating a list dynamically and provinding the id to the selected element when clicking on it. I need to move up - down in the result section of the list ::
function add_to_result() {
//var moparent = document.getElementById("parent").innerHTML;
var moname = document.getElementById("moselect").innerHTML;
var node = document.createElement('LI');
node.setAttribute('onclick', 'giveid_Result(this)');
node.setAttribute('ondblclick', 'fillprops()');
var text = document.createTextNode(moname);
node.appendChild(text);
document.getElementById("result").appendChild(node);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button type="button" class='go_up' onclick="reorder_up(this)" style="height:40px;width:40px">↑</button>
<button type="button" class='go_down' onclick="reorder_down(this)" style="height:40px;width:40px">↑</button>
<div id="results">
<div class="boxheader">
<STRONG>RESULTS</STRONG>
</div>
<div class="boxcontent">
<ul id="result">
</ul>
</div>
</div>
Your jQuery click event listeners are added after the click event happens so they are never handled, on the click event you are just binding the click handler. Move the $().click outside of the onclick and since you are using jQuery selectors for the buttons you can get rid on onclick
$(".go_up").click(function() {
var $current = $(this).closest('li')
var $previous = $current.prev('li');
if ($previous.length !== 0) {
$current.insertBefore($previous);
}
return false;
});
$(".go_down").click(function() {
var $current = $(this).closest('li')
var $next = $current.next('li');
if ($next.length !== 0) {
$current.insertAfter($next);
}
return false;
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button type="button" class='go_up' style="height:40px;width:40px">↑</button>
<button type="button" class='go_down' style="height:40px;width:40px">↑</button>
<div id="results">
<div class="boxheader">
<STRONG>RESULTS</STRONG>
</div>
<div class="boxcontent">
<ul id="result">
</ul>
</div>
</div>
var selected;
for(var x=0;x<5;x++){
addToResult("Node:"+x);
}
$("li").click(function(){
console.log("pressing"+$(this).attr("id"));
select($(this))
});
$(".go_up").click(function(){reorder_up(selected)});
$(".go_down").click(function(){reorder_down(selected)});
function reorder_up(node) {
var dnode=node;
console.log("RUP");
var $current = $(dnode).closest('li')
$current.css("background-color","blue");
var $previous = $current.prev('li');
$previous.css("background-color","yellow");
if ($previous.length !== 0) {
$current.insertBefore($previous);
}
return false;
}
function reorder_down(node) {
console.log("RDO");
var dnode=node;
var $current = $(dnode).closest('li')
$current.css("background-color","blue");
var $next = $current.next('li');
$next.css("background-color","yellow");
if ($next.length !== 0) {
$current.insertAfter($next);
}
return false;
}
// for adding to the result page i am using this function, where i
//am creating a list dynamically and provinding the id to the selected
//element when clicking on it. I need to move up - down in the result section of the list
// ::
function addToResult(id) {
var node = document.createElement('li');
node.setAttribute('id',id);
// node.setAttribute('onclick', 'select(id)');
node.setAttribute('ondblclick', 'fillprops()');
var text = document.createTextNode(id);
node.appendChild(text);
document.getElementById("result").appendChild(node);
}
function select(selector){
selector.css("background-color","green");
console.log("youre pressing"+selector.attr("id"));
selected=selector;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" class='go_up' style="height:40px;width:40px">↑</button>
<button type="button" class='go_down' style="height:40px;width:40px">↓</button>
<div id="results">
<div class="boxheader">
<STRONG>RESULTS</STRONG>
</div>
<div class="boxcontent">
<ul id="result">
</ul>
</div>
</div>
The $(something).click query executes when you click on that something. So it doesn't make sense to put into a function. You want it to trigger some function execution.
I added the dnode var to keep the scope of the node since this is no longer attached to the node when you call reorder node. So I substituted this with dnode and it works fine. Here is the fully working code:
Javascript:
for(var x=0;x<5;x++){
add_to_result("Node"+x);
}
$("li").click(function(){
select($(this))
});
$(".go_up").click(function() {
reorder_up(selectedNode);
});
$(".go_down").click(function() {
reorder_up(selectedNode);
});
function reorder_up(node) {
var dnode=node;
var $current = $(dnode).closest('li')
var $previous = $current.prev('li');
if ($previous.length !== 0) {
$current.insertBefore($previous);
}
return false;
}
function reorder_down(node) {
var dnode=node;
var $current = $(node).closest('li')
var $next = $current.next('li');
if ($next.length !== 0) {
$current.insertAfter($next);
}
return false;
}
You can remove the onclik attribute from html. It is not needed
About the add to result function: There is no element with the moselect id, so moname is null and the compiler gives an error. Next, you never call it so it will never execute. You should add a loop somewhere to add the elements. You don't need to set attribute onclick, just use a jquery
selector.I added set attribute id to pass it to select function. By the way, I don't see give_id function anywhere so I created a function to select the node to be moved
function add_to_result(id) {
var node = document.createElement('li');
node.setAttribute('id',id);
node.setAttribute('ondblclick', 'fillprops()');
var text = document.createTextNode(id);
node.appendChild(text);
document.getElementById("result").appendChild(node);
}
function select(selector){
selector.css("background-color","green");
console.log("youre pressing"+selector.attr("id"));
selected=selector;
}

append html to the div with AngularJS

How can i pass html through in AngularJS controller ?
Here is my list.html:
<div class="col-xs-3" ng-repeat="item in companyData">
<a ng-click="getPackageInfo({{item.iCompanyID}},'{{item.vCompanyName}}')" class="block panel padder-v bg-primary item">
<span class="text-white block">{{item.vCompanyName}}</span>
</a>
<div id="packagehtml"></div>
</div>
<div id="lp" class="col-md-12 listing-div hidden"></div>
in controller.js:
$scope.pData = [];
$scope.getPackageInfo = function(id,name) {
$scope.name = name;
var summery = SubscriptionoptioncompanylistFactory.getSummary(id);
document.getElementById("lp").classList.remove("hidden");
$('.packages-data').html('');
$('#loading').show();
SubscriptionoptioncompanylistFactory.getPackageInDetail(id).
success(function(data) {
if(data != 0) {
$("#lp").html(summery); // this is used to append the data
document.getElementById("np").classList.add("hidden");
Array.prototype.push.apply($scope.pData, data);
$('#loading').hide();
} else {
document.getElementById("lp").classList.add("hidden");
document.getElementById("np").classList.remove("hidden");
$('#loading').hide();
}
});
};
Here, I have wrote $("#lp").html(summery);, in that div I have to append html which comes from var summery = SubscriptionoptioncompanylistFactory.getSummary(id);. But this is not going to append the data. In console I can see that data comes in summary variable. How can I do?
have a look at below modifications
Use angular ng-show for showing/hiding elements
Use data binding and avoid Jquery like Dom manipulation
<div class="col-xs-3" ng-repeat="item in companyData">
<a ng-click="getPackageInfo({{item.iCompanyID}},'{{item.vCompanyName}}')" class="block panel padder-v bg-primary item">
<span class="text-white block">{{item.vCompanyName}}</span>
</a>
<div id="packagehtml"></div>
</div>
<div id="lp" ng-show="lbVisible" class="col-md-12 listing-div hidden">{{summaryBinding}}</div>
and the controller would look like :
$scope.pData = [];
$scope.getPackageInfo = function (id, name) {
$scope.name = name;
var summery = SubscriptionoptioncompanylistFactory.getSummary(id);
$scope.lbVisible = true; //document.getElementById("lp").classList.remove("hidden");
$('.packages-data').html('');
$scope.loadingVisible = true; //$('#loading').show();
SubscriptionoptioncompanylistFactory.getPackageInDetail(id).
success(function (data) {
if (data != 0) {
$scope.summaryBinding = summery; // $("#lp").html(summery); // this is used to append the data
$scope.npVisible = false; // document.getElementById("np").classList.add("hidden");
Array.prototype.push.apply($scope.pData, data);
$scope.loadingVisible = false; // $('#loading').hide();
} else {
$scope.lbVisible = false; //document.getElementById("lp").classList.add("hidden");
$scope.npVisible = false; //document.getElementById("np").classList.remove("hidden");
$scope.loadingVisible = false; // $('#loading').hide();
}
});
};
your snippet is not showing elements that you use :
np, #loading so just find them and add the `ng-show` with the proper scope variable : `npVisible , lbVisible , loadingVisible`
and note that we add the data using summaryBinding
hope this helps :)

How to dynamically change attributes depending on JSON data?

I have the following miniapp:
[![enter image description here][1]][1]
When clicking on the elements on the left list, the info should change dynamically on the right div in relation to that clicked element.
I could get it work statically, but I don't know how to make it dynamic.
I have a JSON file with the data, and data is loading correctly and being parsed correctly.
data = '[{"name": "Hotel Sunny Palms","imgUrl": "images/sunny.jpg","rating": 5,"price": 108.00},{"name": "Hotel Snowy Mountains","imgUrl": "images/snowy.jpg","rating": 4,"price": 120.00},{"name": "Hotel Windy Sails","imgUrl": "images/windy.jpg","rating": 3,"price": 110.00},{"name": "Hotel Middle of Nowhere","imgUrl": "images/nowhere.jpg","rating": 4,"price": 199.00}]';
And I have the following HTML file:
<section class="container clear">
<div class="header">
<img class="logo" src="images/lmn-logo-white.svg">
</div>
<div class="inner-container clear">
<aside class="hotels-list">
<ul>
<li class="hotel">1</li>
<li class="hotel">2</li>
<li class="hotel">3</li>
<li class="hotel">4</li>
</ul>
</aside>
<article class="hotel-description">
<div class="hotel-description-container clear">
<div class="hotel-pic-container">
<img id="hotel-pic" src="images/sunny.jpg" height="130px">
</div>
<div class="hotel-info">
<h6 id="hotel-name" >Hotel Sunny Plans </h6>
<div id="hotel-rating" class="hotel-rating"></div>
<div id="hotel-price" class="hotel-price">
$180.00
<span>Total hotel stay</span>
</div>
</div>
</div>
</article>
</div>
</section>
My JS file is this: I get the data to change, but in a static way. Basically what it does is find all the li items and change the info on the right div when clicked.
var hotelData = JSON.parse(data);
document.addEventListener('DOMContentLoaded', function() {
var hotels = document.getElementsByClassName("hotel");
for (var i = 0; i < hotels.length; i++) {
hotels[i].addEventListener('click',function()
{
this.style.background = "#ccc";
this.style.color = "#fff";
var hotelName = document.getElementById("hotel-name");
hotelName.innerHTML = hotelData[this].name;
var hotelPrice = document.getElementById("hotel-price");
hotelPrice.innerHTML = "$" + hotelData[this].price + ".00" + "<span>Total hotel stay</span></div>";
var hotelPic = document.getElementById("hotel-pic");
hotelPic.src=hotelData[this].imgUrl;
var hotelRating = document.getElementById("hotel-rating");
if (hotelData[0].rating == 0) {
hotelRating.style.backgroundPosition = "0px 18px";
}
else if (hotelData[0].rating == 1) {
hotelRating.style.backgroundPosition = "0px 36px";
}
else if (hotelData[0].rating == 2) {
hotelRating.style.backgroundPosition = "0px 54px";
}
else if (hotelData[0].rating == 3) {
hotelRating.style.backgroundPosition = "0px 72px";
}
else if (hotelData[0].rating == 4) {
hotelRating.style.backgroundPosition = "0px 90px";
}
else if (hotelData[0].rating == 5) {
hotelRating.style.backgroundPosition = "0px 108px";
}
});
};
});
Any advice? Thanks!!!
If you are okay with jQuery then here is the quick and very simple solution:
$(function () {
var hotel_list = '';
$.each(data, function(index, hotel) {
hotel_list += '<li class="hotel" data-index="'+ index +'">'+ hotel.name +'</li>';
});
$("aside.hotels-list ul").html(hotel_list);
$(document).on("click", "li.hotel", function () {
var index = $(this).attr('data-index');
load_hotel_info(index);
});
function load_hotel_info(index) {
// Assuming the data variable is global...
if(typeof data[index] !== undefined) {
var hotel = data[index];
$("#hotel-pic").attr('src', hotel.imgUrl);
$("#hotel-name").html(hotel.name);
$("#hotel-rating").html(hotel.rating);
$("#hotel-price").html(hotel.price + '<span>Total hotel stay</span>');
}
}
load_hotel_info(0); // When the page loads for the first time it should show the first item info on the right.
// If you are loading data from ajax then this won't be necessary.
});
In this way the hotel list in the side will also load dynamically. And there isn't much to make it work. Just load the jquery by a script tag before the above code.
I hope it helps.

Adding new thumbnails to dropzone.js after initialization

I have a web page that uses dropzone.js. My web page lets people choose their profile picture. If they have already set it, I want to show their picture, but allow them to change it. In an attempt to do this, I'm using the following dropzone code:
var currentPicture = null;
function removeCurrentPicture() {
try {
if (dropzone) {
for (var i = 1; i < dropzone.files.length; i++) {
dropzone.removeFile(dropzone.files[i-1]);
}
}
} catch (ex1) {
console.log(ex1);
}
return false;
}
function setThumbnailWidths() {
var thumbnails = $("*[data-dz-thumbnail]");
for (var i=0; i<thumbnails.length; i++) {
$(thumbnails[i]).css('max-width', '150px');
}
}
var pictureDropZone = new Dropzone("#myPicture", {
url: "/profile/picture/",
maxFilesize: 5,
clickable: true,
uploadMultiple: false,
previewTemplate: previewTemplate,
previewsContainer: "#previews",
init: function () {
dropzone = this;
// add picture if it exists
var pictureUrl = 'DYNAMICALLY POPULATED FROM SERVER';
if (pictureUrl) {
var pictureSize = // POPULATED FROM SERVER;
var pictureFileName = // POPULATED FROM SERVER;
var pictureMimeType = 'img/png';
var currentPicture = { name: pictureFileName, size: pictureSize, type: pictureMimeType };
this.addFile.call(this, currentPicture);
this.options.thumbnail.call(this, currentPicture, pictureUrl);
this.files.push(currentPicture);
$('#picturePrompt').hide();
}
this.on('addedfile', function (file) {
if (dropzone.files.length > 1) {
removeCurrentPicture();
}
$('#picturePrompt').hide();
$("#errorMessage").hide();
});
this.on('removedfile', function (file) {
$('#picturePrompt').show();
});
this.on('success', function (file, res) {
setThumbnailWidths();
});
this.on('error', function (e, m) {
$("#previews").hide();
$("#errorMessage").html('An unknown error has happened. Please try again.');
$("#errorMessage").show();
});
}
});
The HTML that complements this dropzone looks like this:
<div id="myPicture" style="padding:40px; cursor:pointer;">
<div id="picturePrompt">Drop a picture here or just click</div>
<div id="errorMessage" class="error" style="display:none; margin-bottom:8px;"></div>
<div class="files" id="previews">
<div id="template" class="file-row">
<ul class="list-inline">
<li>
<span class="preview" style="width:350px;"><img data-dz-thumbnail /></span>
<p class="size" data-dz-size></p>
</li>
<li style="vertical-align:top;">
<button data-dz-remove class="btn btn-danger" style="margin-top:8px;">
<i class="glyphicon glyphicon-trash pull-left"></i>
<span class="pull-left">Delete</span>
</button>
</li>
</ul>
</div>
</div>
</div>
This code works unless a picture is loaded from the server when the page loads. In the event that pictureUrl is set, the picture renders fine. I can "delete" it. However, if I try to add a new picture, the new thumbnail does not appear. The size of the file does. But the thumbnail does not show.
What am I doing wrong?

Categories

Resources