There is a lot of code so I can not address every aspect of your code.
##First impression.
It works, just, but is very unfriendly.
###Cursors Cursors are a must when doing any form of mouse interaction. When over a draggable item the cursor should be "grab" and then to "grabbing" or "none" when dragging. The CSS standard cursor set is very limited, learn how to create your own cursors and use them. I can not overstate how important cursors are to good UI design. They are the forgotten information provider in may apps.
###Select drag!
One thing I find it very annoying, even professional sites seem to miss this, Turn off "select drag" when mouse is over draggable items. CSS rule user-select: none;
and appropriate prefixes if needed. It just looks horrible when a big blue area is selected just for dragging something.
###Smarter drop Don't allow dropped items to overlap. Move the dropped item to fit in front of or behind items under it. If you drop over an item and there is another after insert the new item after the current and move the next one to give room.
Snap to the day the mouse is over (if showing it) or to the day nearest the center of the control.
###Scale Use the mouse wheel input to scale in and out (if not over item). The current screen is way to wide. You may also allow that when the mouse is over an item that the mouse wheel moves it left and right. (with appropriate cursor)
###Bits and bobs
- Fade the dragged item so you can see what is under.
- It seems to hold the item sometimes even with the mouse button up.
- Provide a clear disposal icon to allow the item to be removed. Drag block over dispose icon to remove.
- Allow a modifier for creating a copy. Eg [ctrl] drag or Right click drag to copy.
I noticed a comment about touch devices. DONT try and code a touch interface and mouse interface on the same page. Detect the interface and load the appropriate interface
Also someone suggested using a pre existing library. Javascript libraries I find to be very poor quality. If you do use one, befor you do, look at the source code, look at the documentation. If you find the code hard to read and the documentation sparse then don't use it. Just because a lib has a lot of stars (what not) does not make it a good lib. I see more time wasted wrangling inappropriate, overly complex, or just plain unfinished and buggy libs than would have ever been spent creating the functionality you need yourself.
##The Code
###Style!
Before you write another line of code read Airbnb JavaScript Style Guide. Once you have read it, read it again in a week, and agian in a month. Learn it inside out. Style is the most important aspect of coding in any language. Bad and inconsistent style is the leading cause of bugs in all languages.
I personal do not agree with all the style guidelines in the document, but I have sound and good reason for why. If you can not find reason not to adopt a style in the document then do as the document says. The benefits will show as soon as you start coding to the consistent style.
That takes care of style and I will address the code design.
###Code design
The code is all over the place, just a sea of seemingly unrelated functions intermixed with the odd bit of immediate functionality. This is very hard to manage as the code base grows. Break the application up into smaller and related parts.
I was going to add "data does not belong in code" but I see you have commented out the AJAX fetches. Still for experimenting you should still use data external to any of the code.
###Abstractions and modular design.
Your app is mixing core functionality, information , UI and rendering. These things should exist independently of each other. What is the core of the app (to schedule radio shows) It should be able to do all the things that a scheduler is expected to do independently of any UI or Display. It does this via an interface to some core abstract types.
You need to design some objects that together create the core functionality of the app.
What follows is only a suggestion and not at all an in depth analysis of your application. These are only to give example of how modules may relate and communicate.
Some suggested abstract objects. Timeline
, Show
.
Some related functionality. Timeline.addShow
, Timeline.removeShow
, Timeline.nextShowTime
, Timeline.rescedualShow
, Timeline.isTimeFree
, Timeline.showAtTime
, etc...
Show.setName
, Show.getLength
, Show.hasPlayed
, 'Show.getId' etc...
Having the information you are managing separate from the display will make the task of displaying that information a lot easier.
###Renderer and UI
A renderer interrogates the Timeline
and Show
interfaces to workout what to display and where.
A UI interface that is strongly tied to the render and is a middle man between the renderer and the Timeline
, Show
interfaces.
Remember the actual functionality of your app, to schedule play times must be able to function independently of a front end.
###Example of module communication.
The UI asks the renderer "what is under the mouse?" The renders gives a showId
, the ui then asks the timeline, "Can I move the showId
?" If the response is yes it tells the renderer that the cursor should be a grab icon. The render will set the grab cursor at the next scheduled render refresh (use requestAnimationFrame to maintain a render loop)
If you are dragging an item the UI will ask the renderer, "What is the day and time under the dragging item?" You use that information to ask the timeline, "Can the show be dropped at that time?" If so inform the render to show this fact.
The renderer only renders and keeps information regarding the rendering. Information it holds is where and what size the various shows are. Where the timeline is displayed and how screen coordinates relate to time and date. The ui will ask, what time or day is the mouse at, The render can hold identifiers that can be used by itself and the UI to query the timeline and shows
The render asks the Timeline and Show interfaces. Has there been a change to the data that needs to be updated? The render always asked and is never told. The renders is the slow link in the chain of information display, let it keep its own pace.
It may seem like a lot of extra work but in reality if done well it is much more efficient
##You asked;
"What's the best way to handle an element's position in JavaScript?"
Personally I would say, forget the DOM and use a canvas, but that will upset the the believers in semantic page design.
I all I can say is maybe rather than use relative positioning do all elements via absolute positioning, that way you don't have to fight the pages layout engine. If you have correctly separated rendering from the apps function then you are free to experiment with rendering methods.