4

I've been working on a SharePoint site that's been custom branded and run in to an issue with the drag and drop uploader in the document libraries.

For reasons unknown to me, the 'Drop here...' box which should appear on top of the list of files is sitting off to the right and below where it should be. I've attached an image.

I have observed that some JS code is placing inline styles on the div with id="ms-dnd-dropbox". This is obviously the mechanism sharepoint uses to place the div in the right spot, using absolute positioning. The problem is, it's calculating values for 'top' and 'left' which place the box in the wrong spot.

What I need to figure out is how it calculates the 'top' and 'left' values and work out why they are being mis-calculated. I haven't had any success on google so far. Hoping someone can help!

Misplaced drop here box

1
  • I have the same problem...(but I not have the answer yet) it depends on the page layout. I'm using a masterpage from bindtuning.com and if I choose one column, the box it's ok. Then I choose a template with the menu at the left or right, the box it's misplaced. I'll try to solve with bindtunning, and post the answer here, but if you find an answer sooner, please let me know!
    – user33936
    Commented Oct 1, 2014 at 18:04

7 Answers 7

2

The problem comes from having a relative positioned container somewhere between the drag-n-drop element and s4-workspace. If you debug dragdrop.js, you will see that there is a function called dropElementDragEnter, which creates and places the inline style on of the drop box. It is dependent on a init.js function called AbsLeft, and AbsTop. Basically, these functions find the total positioning of every parent from the element to the body tag, and set that value to the left and top values. Any element having relative positioning will throw that off. I am implementing Bootstrap in my design and had a col-md-12 div wrapped around my content which carries relative positioning.

You can either fix this by js or css...

Overwriting the AbsLeft and AbsTop functions almost worked for me by using jQuery position function, except that the dropElementDragEnter function was also adjusting the position by the offset of s4-workspace. Then I had difficulty overriding that function based on when dragdrop.js was loading.

I quit fighting SharePoint and just altered my css. In my case, I always know where the drag box should be, so I placed the drop box accordingly...

div#ms-dnd-dropbox {top: 0 !important;left: 15px !important;}

Hope this helps!

2

@BM- really hit the jackpot on this one. Really nice solution. I noticed though that you need to add the correct class to the under s4-workspace. Like this:

<div class="ms-dnd-dropbox" id="ms-dnd-dropbox" style="display:none;">
<span class="ms-attractMode ms-noWrap" id="ms-dnd-dropboxText" style="line-height: 324px;">Drop here...</span>
</div>

Otherwise it seemed for me that the dropbox 'area' generated correctly on DropBoxDragEnter but stayed on top of the webpart even on "mouseleave". To add the class solved that issue.

EDIT

With some more testing i've noticed that this only will work if your responsive page has one webpart with drag and drop functionality. I.E this will not work with sevral document libraries on one page for example. The fix will only affect the first library in the DOM and will leave the rest of the libraries as they where.

2

I had a similar problem to this, and indeed had attempted a solution similar to @Sean M. However, this runs into a more bizarre problem if you have more than one library part on the page, especially if they are in different relatively positioned divs. Intiially I tried:

.ms-webpart-chrome {position: relative;}
#ms-dnd-dropbox {left: auto !important; top: 15px !important}

This results in almost correct behaviour, but behaves oddly if you try using more than one library between page refreshes. Dragging a document over any library will position the dropbox over that library correctly, but then dragging a document over any other library will render the dropbox in the position of the first library (albeit, with the size of the correct library).

The solution was to identify that dragdrop.js first looks to see if #ms-dnd-dropbox exists somewhere on the page, set top and left if it does, or create it within the document library webpart that triggered the script. However, as @Sean M pointed out, if your webpart is in an element other than s4-workspace that has a non-static position, this will result in dragdrop.js having the wrong reference positions.

Since dragdrop.js looks for #ms-dnd-dropbox first, why not just add it directly to the masterpage? There will only ever be one, and if it's hidden otherwise, it won't affect anything else. Just add:

<div id="ms-dnd-dropbox" style="display:none;">
    <span class="ms-attractMode ms-noWrap" id="ms-dnd-dropboxText" style="line-height: 324px;">Drop here...</span>
</div>

as a direct child to s4-workspace, and dragdrop.js won't attempt to create a dropbox within any webparts: all dropboxes will return to their correct positions!

EDIT

So it appears that I was working with an older version of SharePoint at the time I wrote this, and that SharePoint has updated dragdrop.js in the meantime.

Dragdrop.js removed the odd "we'll build one dropbox wherever, and move it to all the others as they are dragged over" mechanism, and instead replaced it with "everyone who needs a dropbox gets their own." Unfortunately, this renders my previous solution useless. As was pointed out by @Kodz, dragging over the library would cause the dropbox to be created, but dropping a file or dragging off the box causes dropbox.js to throw an error.

Investigating further, the new version of dropbox.js creates a "relatedWP" attribute on the box, associating the box with a specific webpart; and thus each webpart receives it's own box. This attribute is necessary in the new version to identify the status of the current control. Unfortunately, the SharePoint update has not fixed the actual problem - that is, the bootstrap grid divs (or other, responsive design divs) have position: relative attributes, and thus confuse the library in it's setting of top and left.

The strategy, though, remains the same: move the dropbox divs to #s4-workspace. Unfortunately, you can't hardcode it in the masterpage any longer. Instead, they need to be moved once they are created. Fortunately, they are all created simultaneously for all parts on the page, or at least are doing so currently. Unfortunately, they still are created on first dragover, rather than page load...

Moving them once created is simple:

$("#s4-workspace").append($(".ms-dnd-dropbox").detach());

will do the job. However, identifying when they are created is a little more difficult. Fortunately, there are some libraries that take advantage of DOM Mutation Observers to achieve this goal. I downloaded and installed into SharePoint Live Query, and added the following jQuery:

;(function() {
    $(document).ready(function(){
        $(".ms-webpart-chrome").livequery(".ms-dnd-dropbox", function() {
            $("#s4-workspace").append($(".ms-dnd-dropbox").detach());
        });
    });
})();

This is not perfect; unfortunately the dropboxes are created visible, and so on first dragover, there is a slight flicker as the boxes return to the correct positions. All other dragovers will not have this issue; however.

I will also note that the livequery library should continue to find .ms-dnd-dropbox elements as they arise, and move them to the #s4-workspace, so even if the boxes are not created simultaneously on first dragover, this still should work.

1

I went for a quick and flexible solution that will work for 1 or many libraries on the page.

Instead of trying to fix the positioning of the drag and drop div for the corresponding library webpart, I suggest to use all space for the drag and drop area. Better user experience as well I think.

enter image description here

div#ms-dnd-dropbox {position: absolute !important; top: 70px !important; !important; width: 97% !important; height: 95% !important;}
1
  • 1
    Except for the fact that it can be hard (if you have many libraries on the page as you state) to tell to which library you are dropping the file! Commented Nov 24, 2015 at 11:31
0

Thank you for this thread.

I was able to to resolve my issue by inserting the following in a content editor web part on my page where I had ben using Bootstrap. I had to match the relatedWP to the specific webpart.

<div id="ms-dnd-dropbox" class="ms-dnd-dropbox" style="display: none;" relatedWP="WebPartWPQ6"></div>
0

add this in your custom css

div[id^=MSOZoneCell_] {
    position:relative;
}
#ms-dnd-dropbox{
    left:0 !important;
    top: 0 !important;
}
0

I fixed this by moving the 'ms-dnd-dropbox' div into 's4-workspace' div, because in my case, the dropbox div was within divs that had bootstrap classes added and that was offsetting its position, so moving it outside of these divs solved the problem.

Here is the jquery code I used:

var webPartDivID = 'asdfasdfasdf'; //get the doc lib web part ids in the page and run the code below on all of them.

$("div [webpartid=" + webPartDivID + "]")[0].addEventListener("dragenter", function () { setTimeout(function () {

                                    }, 50);

                                    if ($("#s4-workspace")) {
                                        if ($("#ms-dnd-dropbox")) {

                                            $("#s4-workspace").append($("#ms-dnd-dropbox"));
                                        }
                                    }
                                });

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.