Building drag and drop navigation tabs - javascript

I'm working on building a new website purely for learning purposes and I want to try and implement some drag/drop sorting system. I am aware that jQuery provide the sortable UI component http://jqueryui.com/sortable/ but I want to have a go at designing and building the system from scratch (seen as this is for learning purposes).
When it comes to Javascript I have to admit I am fairly novice, so I was wondering if any of you could offer your 2 cents against my current thinking of how the program would work:
An un-ordered list sits at the top of the page (navigation bar), each item is assigned a the class 'draggable x' where x is its current position in the list
An event listener is bound to each li element within the list
When an on-mouse-down is made on an element a variable is set telling which cell has been clicked, this then creates a thumbnail under the cursor (hides the old cell) and allows the user to drag
When the mouse is released the list item is slotted into its new position by updating its class number, whilst decrementing all class numbers behind it
Questions:
1) My main problem with this is, how do I detect when I have passed another li element when dragging? I could assume width n has been passed, but each cell could be of variable length making that solution inappropriate.
2) I am also assuming I am going to need to use AJAX to handle the callback, otherwise I am going to get some undesired page refreshes (right)?
Hopefully this won't receive down votes - I want to stress that I am NOT seeking a solution from you guys, I have used these forums long enough to know that I don't demand code from the community without providing any of my own work! I'd just like some feedback on my initial draft as well as answers to the 2 questions asked above.
Thanks in advance for your time
Alex.

If you are using JQuery you can avoid having to know what order your items are in.
The .index() function will return the position of the item relative to its siblings.
You can then simply keep track of the element you want to move by adding a working class to it on a mouse down even. (I use .draging in my example)
On the mouseup event just find our old item by the class you added. Depending on which element is first compared to the other, insert your working element before or after the element you mousedup on and then remove your working class.
Here is an example
http://jsfiddle.net/V72Le/2/
function swap(dragable, draging) {
//find direction of move then move item based on direction
var from = $(dragable).index();
var to = $(draging).index();
if (from > -1 && to > -1) {
var direction = from - to;
if (direction > 0) {
$(draging).insertAfter($(dragable));
} else if (direction < 0) {
$(draging).insertBefore($(dragable));
}
}
}

Related

How to make custom scrollbar that shows highlighted items on the page

I am a student (beginner coding level) coding a prototype and I am trying to make a custom scrollbar that shows highlighted markers of selected items on the page, similar to VS. I was wondering if anyone might help me with this or be able to point me to a source that shows examples of how to do this?
We have html, some css and javascript coded. I am a beginner so I have I have tried searching on websites for examples but have found none.
Our Javascript for selecting items:
$('.highlight').click(function () {
// Get the second class name of the parent li
var highlightClass = $(this).parent().parent().attr('class').split(' ')[
var highlightItem = '.' + highlightClass + ' > .menuDiv'
$(highlightItem).toggleClass('highlight-show')
})
The user should be able to select an icon that highlights that object from a long list of other objects, and then scroll down the page to be able to see all of the objects of the same ID that have been highlighted. There are multiple objects with the same ID on the page, so they would all be highlighted when the user selects one of them.
With the final result, those highlighted objects would show up as 'ticks' on the scrollbar so the user can easily find them on the page. This functionality would be used so that the user can easily find a certain item from a long list of items.
Thank you in advance.

Retaining Memory of Initial Properties for Dynamic Buttons

I want to make a very simple mix and match system, where the user chooses items from a select drop down menu which triggers things. I have buttons that are appended to the document in a rather off the cuff manner, that is to say, whenever the user chooses something from the select some text will appear as well as a button to remove that text (and corresponding button). I'm using D3 to manipulate selections, add classes and append things. I use classes to tell the button which text to remove. All that being said, I believe this still could simply be a native javascript problem I'm running into. The problem is as follows:
After you choose some things from the select drop down menu, and then proceed to click the x buttons in the order bottom to top, the behavior is as desired. However, if you click a button at the top or in the middle, the button will not remove the right text. I believe that is because the button is simply removing whatever the latest string value of the dynamic class I'm using. That makes me doubt that the button actually retains the initial properties of its .on('click', function() {}) (hence the post title).
If that's the case, I'm not really sure how to circumvent such an issue, as the buttons are dynamic in nature.
Very short and simple example here.
No need to retain memory kind of thing just make sure your element is accessible one such scenario would be to save the id reference of element as class of another element like this
d3.select('body').append('button')
.text('X')
.attr('id','b'+(intCount+1))
.attr('class',choice+'1') //class is the id of the text element
.on('click', function(d,i) {
var t = d3.select(this).attr('id')
var c = d3.select(this).attr('class')
var thisChoice = choice;
d3.selectAll('.' + t).remove(); //remove this element
d3.selectAll('.'+ c).remove(); //remove text element
intCount -= 1;
count -= .7;
});
working FIDDLE

Aurelia JS - multi level binding/update?

I'm not sure whether I'm using the right terminology here - but here is an example:
https://gist.run/?id=57ed46429e4583eb4c3fb11814451a55
This is how it looks like in Chromium:
Basically, the entries on top (red outline) are a visualization of an array as the "first-level" data display; here one can toggle each element's selection, and make a multi-element selection (red background). The array that is the source of the "first-level" display is mydata in first-level-items.js.
Those items that are selected in "first-level", are then shown again in "second-level" (green outline); here the same information of name and value is displayed, although a bit differently. Here also one can toggle an elements selection - but only one "second-level" element can be selected. The array that is the source of the "second-level" display is myseldata in second-level-items.js.
The intent here, is that once a "second-level" selection has been made, a slider appears, to change the .value property of the particular object which is the selected array element.
My original question (which is why I started this post/example at all), was:
How do I ensure that whenever the slider is changed, the value is updated in both second-level and first-level display?
... however, for reasons beyond me, this in fact does work somewhat in this gist.run example (but it still doesn't work in my actual project, which forced me to come up with the example to begin with). Also it only works somewhat, in the sense that when loading the example page at first, after making first and second level selections, and then changing the slider, the .value will be updated in both first- and second-level display. But as soon as I try deselecting on second level - or changing the selection on second level - then updating stops. So, I guess this question still stands...
After a second-level selection has been made, deselecting on second level (by clicking to toggle) does NOT remove the slider; how can I have it behave like that?
The update happens only on the slider's onChange - basically, while you drag and slide, this component emits onSlide, but it will generate onChange only at the end when the mouse is released (that is, when the sliding has stopped). How can I update both first- and second- level display while the slider is sliding?
And finally - is this how this kind of a problem is best addressed in Aurelia? That is - I currently have one array in first-level-items.js; first-level-items.js then has a singleton reference to second-level-items.js, so it can call a method within it, to change a filtered copy of the array on the second level, which then serves as a source both for second-level display and the slider... Is there a better way to organise this?
Boy, this was a pain, but here's what I think is the solution:
https://gist.run/?id=c09fea3b82a9ebc41e0a4c90e8665b04
Here are some notes:
Apparently, there is something wrong applying if.bind or show.bind on the input element of the slider - instead, the input element should be put in an enclosing div, and the div should have if/show.bind applied
Furthermore, if.bind should not be used, as it re-instantiates the slider element - use show.bind so we can get a reference to the slider widget at start already, even if it is hidden
Seemingly, using TaskQueue in attached() is the only way to get a reference to the slider at start
Once we have a reference to the widget, re-apply it on each second level element, whenever they change
Do not set this.myselChanging to null to specify no target of the slider (simply count on hiding the slider appropriately)
For a continuous change (onSlide), simply use this.myselChanging.value = e.value; in the handler - both first-level and second-level values will be changed
Beyond this, it seems arrays are copied by reference, so the multi-level update happens without further intervention...
Though, would still love to know what is the proper way to do this...

Increment when element becomes visible?

I am working with the skrollr plugin.
I have a set of arrows. One points down and the other up. When you click the down arrow it takes you to the next section/chapter of the animation. Right now it works great. But my issues is lets say the user does the following:
He/she scrolls half way through the page(lets say section 5). They then decided to see how much of the animation is left. So they click the next section arrow.
This user will be put to section 2 even though they are at section 5 because I have no way to detect when the user hits each section so I can update the arrow #hrefAnchor.
What I was thinking is adding an interval/ event listener that would detect when the section is visible on the DOM and update the arrows to take you to the previous and next sections.
Does anyone know how I can approach this idea?... and will work in ie >= 9
If you're willing to modify the Skrollr library, something I had done was add:
else if(prop === 'javascript') {
eval(val);
}
as an option in skrollr.setStyle which allows then for you to add a hook for arbitrary JavaScript code on elements like each section here using data-XXX="javascript:myFunction();" and I believe Skrollr will even still interpolate numbers in your arguments for you.
If you have control of what gets executed when "next" is clicked, can you check the scroll value at that time to determine which section it is between and switch on that to send them to the appropriate section? Essentially, rather than trying to keep the target current at all times which is wasteful/difficult/error prone, just calculate it when it matters - when the click occurs.
If you give your element a class like "visible", you could select all the visible elements by using jQuery:
$(".element.visible:last-of-type").on("click", function() {
});

Highlight last inserted document in Meteor

I have form and list of objects at the same page. When I insert a new row, it is not very easy to see where the newly inserted row is placed. Therefore, I thought I could color/highlight the newly inserted row (and perhaps remove the highlight after a few seconds).
How can I do this? I think a way to do this could be using a method on the server which returns the inserted id (return Collection.insert(doc);) and on the client use a callback with
Meteor.call('insertDoc', function(err,result) {
// do something with result
});
I think I can use a reactive-var to save the id of the last inserted row and in the loop highlight the row with
{{#each docs}}
<li class="{{isActive}}">{{name}}</li>
{{/each}}
and have a helper to return active if this._id equals the reactive var with the last inserted id.
But is this the best way to do it? How can I remove the color after some seconds? I have seen such behaviour on many pages but I cannot find any tutorials/code snippets to achieve this.
I wrote a package that uses Meteor's UI hooks to fade items in and out of a list as they are added and removed, to help users maintain context as data changes:
https://github.com/mizzao/meteor-animated-each
There is a demo at http://animated-each.meteor.com/. You can see that as items are added and removed, they are faded in and out. If items are inserted off the screen, the visible area does not scroll.
This isn't doing exactly what you want, but you can use the same idea to highlight items as they appear as well, as opposed to the simple fade in.
Note that all of this happens at the UI rendering level - not the template/code level. The UI hooks are also not well documented right now, but they've been around for a while.
I don't know if your method is the best, but that's how I'd go about doing it.
As for the animation, I'd use a CSS3 animation. Plenty to choose from ( https://developer.mozilla.org/en-US/docs/Web/CSS/animation ), and you can easily make them fade to the standard color. The animation would also only be applied to the last inserted item (because of the way you did it, only the last item would have the "active" class)

Categories

Resources