Using contextMenu plugin with fileTree plugin without losing draggable support - ruby-on-rails

The server is running off Ruby on Rails. Javascript is written using Coffeescript.
I am currently using the jQuery File Tree plugin with the Context Menu plugin. Both are working at the moment, with one minor problem. I also have draggable enabled in the file tree and it will not cancel after the left click is released. In the picture below, the mouse has been released already.
Mouse up but draggable hasn't cancelled
The page this is loaded on has one div:
<div id="file_tree"></div>
And this div is filled by another page from a different controller. The code is:
<ul class="jqueryFileTree" style="display: none;">
<% #contents[0].each do |directory| %>
<li class="directory collapsed"><%= directory %></li>
<% end %>
<% #contents[1].each do |file| %>
<li class="file ext_<%= File.extname(file)[1..-1] %>"><%= file %></li>
<% end %>
</ul>
This page also loads the draggable code:
$ ->
#settings =
revert: true
helper: "clone"
containment: "#file_tree"
axis: "y"
scroll: true
cursorAt:
top: -2
$(".directory").draggable(#settings)
$(".file").draggable(#settings)
And the context menu is added like this:
$("#file_tree").contextMenu { menu: 'filetree_context_menu' }, (action, element, position) =>
#on_context_menu(action, element, position, data.root_directory)
Where #on_context_menu is simply a function (it has no bearing on this problem though).
The problem can be stopped (the clone returns to its original) if you click outside the #file_tree div. However, it appears that click, mousedown, and mouseup events are handled correctly. Also, the context menu has no problems and will not induce the draggable problem.
In regards to my searching around for fixes, I have found nothing. The File Tree plugin has an okay amount of information floating around, but the Context Menu one seems to have next to nothing (must be unpopular?). And none of those have both at the same time. If you need some other information, please state.
EDIT: I figured out that this is actually because the plugin needs to call e.stopPropogation() on the mouseup event to prevent it from opening a real context menu. Anybody know how to manually perform a stopdrag() event? It's not working if I call $(this).trigger('stopdrag') in case you were going to suggest that.

Eventually fixed this problem (after quite a while, and while procrastinating to get a Tumbleweed). Just added a check that it was the right button that was clicked, because it was breaking drag by running e.stopPropagation() on BOTH clicks. It's much cleaner than my original work-around that I scrapped.
if(e.button == 2) {
e.stopPropagation();
}

Related

Making first mobile Safari tap a 'clickable action'

I have seen variations on the theme, but no clear answer. Basically I want an AngularJS Directive that registers a click and inserts extra content into a page, and then scrolls down a bit to make the new content visible. Here is the HTML
<li class="btn btn-default" ng-show="resto.link !== 'none'">
<p scroll-down onclick="void(0)">
Full review
<span class="glyphicon glyphicon-chevron-right right"></span>
</p>
</li>
</ul>
<div class="row">
<div class="col-xs-12" ng-bind-html="fullReview">
</div>
</div>
The onlick part is an Apple suggestion, that seems not to work.
And then I have:
.directive 'scrollDown', () ->
restrict: 'A'
link: (scope, $elm, attrs) ->
$elm.on 'click', (e) ->
e.preventDefault()
scope.getFullReview () ->
console.log "Scrolling'
$("body").animate
scrollTop: $elm.offset().top - 100
, "slow"
getFullReview() updates the model after an AJAX call, and then runs the callback.
This works fine in Chrome but not on the iOS simulator - basically a first tap makes the page move (but without triggering the console log - I think this is the URL bar regrowing) and a second is needed to trigger the Directive's link function. I have also installed fastclick as that was mentioned in some posts, but it did not help.
Need ideas :-) (Even some code that would tell me what event is being triggered by safari)
OK, Wow, I do not understand why, but the html above was the last markup on the page, so all of this was happening at the bottom of the screen. When I added some extra margin to the <ul> element, everything started working perfectly!! Bug in Safari?

I got jquery-ui sortable working with meteor templates, but is it a bad hack?

I'm trying to use jquery-ui sortable with nested templates in Meteor, as follows. Here are the two templates in question:
<template name="activityEditor">
{{! the main activity editor view }}
<div class="activity-editor">
<input type="text" name="title" class="input-xxlarge" value="{{info.title}}" placeholder="Type a title here...">
<div class="activity-steps">
{{#each info.steps}}
{{>activityStepEditor}}
{{/each}}
</div>
</div>
</template>
<template name="activityStepEditor">
{{! the container view for each step editor }}
<div class="activity-step" data-id="{{_id}}">
<div class="order">{{order}}</div>
{{!....stuff...}}
</div>
</template>
and the template code (using coffeescript):
_.extend Template.activityEditor, {
# ...stuff...
rendered: ->
$(".activity-steps").sortable {
items: '.activity-step'
handle: '.order'
update: ->
stepIds = ($(el).attr('data-id') for el in $('.activity-step'))
$('.activity-steps').empty() #this must be done in order to steps to re-render properly
Lab.Activity.reorderSteps stepIds
}
$(".activity-steps").disableSelection()
}
The only way I can get this code to work and properly rerender the order is by emptying the container of my sortable elements right after they update with $('.activity-steps').empty(). I've tried cancelling the update event and forcing a rerender by changing another variable watched in the context, but any change causes Exception from Meteor.flush(): undefined after which I can't rerender anything until page reload.
This seems to work, and everything rerenders great. So my question is: is there any reason why I shouldn't do this? Is there a better, standard practice way to handle the sortable that I'm not seeing?
In the near future there'll be a better way to do it, as Meteor team is developing its new rendering engine: http://youtube.com/watch?v=ISNEhPG0wnA
(in this video, Avital Oliver shows exactly a way to do it without redrawing the screen: the object in the list is actually moved on all clients)
See this Meteor's Github Wiki entry for more technical info:
http://github.com/meteor/meteor/wiki/New-Template-Engine-Preview
While that's not officially published, if you need it right now, you could try Nazar Leush's approach:
http://github.com/nleush/meteor-todos-sortable-animation
He also published a working example here: http://todos-dnd-animated.meteor.com

Combining jQuery UI Tabs and jScrollPane fails

I have problem getting newer version of jscrollpane to work with jQuery UI tabs.
I get only one tab (first one) working, but no others; i tried fix explained here with previous version, placing additional <div> controlled by tabs (and inside are divs controlled by jScrollPane) , as described here, but still with no luck. Has anyone experienced simmilar issues ? Thanks for clues!
I came to solution at last more/less on my own, of course with help by looking at this explanation given by jscrollpane author himself about this issue, but for previous version of jscrollpane.
As this did not work out of the box, and i still had problems implementing the solution, i added a click listener to tabs links, and when clicked, added jscrollpane to content div, like this
jQuery("#tabs ul li a").click(function () {
clickednum = "#tabs-" + jQuery(this).parent().attr("id");
jQuery(clickednum + " .skroler").jScrollPane();
});
what i am doing here, is to wait for user to click on some tab link, and then add jScrollPane to tab content that coresponds to clicked tab link.
.skroler is an extra-div where is tab content, because it is described by script author that it must be done this way in order to work)
I am reckognizing tabs by li id attribute (which i was in need to generate from PHP. for other reasons)
This is specific implementation - from working example, probably it could be done simpler in other environment.
Ah, and of course, at the start of the story, you need to initialize jScrollPane to first opened tab like
jQuery("#tabs-1 .skroler").jScrollPane();
I have the same problem and solved it by adding ids to the li tags that correspond to the generated tabs:
<ul>
<li id="details">Details</li>
<li id="history">History</li>
<li id="examinations">Examinations</li>
<li id="diagnosis">Diagnosis</li>
</ul>
Then, for example:
$('#diagnosis').click(function() {
$('.diagnosis').jScrollPane();
});
Just ran into the same issue
$( "#tabs" ).tabs({
//for the initially loaded tab
create: function( event, ui ) {
$(ui.panel).jScrollPane();
},
//for the tabs opened later
activate: function( event, ui ) {
$(ui.newPanel).jScrollPane();
},
});
More info here http://api.jqueryui.com/tabs/

Trying to understand - HTML replacements and scripts having access to replaced elements on the page

I have a page with a ticket list. In it, there is a <td> that is either a grab or release link. That link inside the '' is wrapped in a '' for an ajax html replacement. Like:
<td>
<div id="ticket_grab_release_<%= ticket.id %>">
*---- either a grab or release link here ----*
<div>
</td>
So, the user clicks on 'grab': They are assigned the ticket, the worklist is updated with their info on the page via HTML replacements, and the grab link is replaced with a 'release' link.
Next to this is a 'complete' link. When the user clicks on that, a small complete form opens in a jQuery UI-Dialog window. I ran into a problem though because along with the grab/replace link changing I also had to toggle this 'complete' link with a grey non-link 'complete' or an actual 'complete' link (if ticket released - disable complete link or visa versa).
The problem is that if this 'complete' link was greyed out and I replaced that with a 'complete' link, the UI Dialog window would not open. Like (no idea what I'm saying) the link wasn't in the DOM.
I got frustrated for a bit and then tried wrapping the script in a <div> and doing an html page replacement on the whole script. I HTML replaced the greyed out 'complete' with a 'complete' link and then HTML replaced the script right after. Interestingly that worked, but I'm really curious as to why it worked. When you ajax insert a script through an HTML replacement, does that inserted script have access to the modified DOM where the original script only has access to the what was the original DOM from the page load?
<div id="html_replace_sript">
<script type="text/javascript">
$('.complete_ticket_link' ).click(function(){
var url = $(this).attr("href");
$("#form_load").load(url,
function() {
$(this).dialog({
modal:true,
draggable: true,
resizable: false,
width:'auto',
height:'auto',
title: ' Complete Ticket ',
position: [125, 50]
});
});
return false;
});
</script>
</div>
Thanks - much apprecaited!
Check out live()'s much less recource-demanding counterpart: delegate()
Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements.
That means that instead of having to look through the entire window for an element, it starts at the specified root, significantly reducing overhead. This is the best solution for your issue.
The answer is YES.
But if you want to bind events to elements that match the selector now and in the future, you can use .live()
So you'd do:
$('.complete_ticket_link' ).live('click' function(){
...
});
Using this, your code can be on your main page and it will work.
Hope this helps. Cheers

Jquery UI panel resizing on click

I am using Jquery Ui panels.([http://code.google.com/p/ist-ui-panel/][1])
While loading the application, everything is fine like collasible, draggable etc.
But i want to make the panel collapsible while clicking on some links.fo ex:
This code will run when the form is loading....
$('#myNews').panel({
'collapsible' :true,
'stackable':false,
});
The html
<div class="panel" id="myNews" >
<h3>Poll</h3>
<div>Some content</div>
</div>
I want to make 'collapsible' :false when clicking some link.... like this
$('#click1').click(function() {
$('#myNews').panel({
'collapseType':'slide-right',
'collapsible':false,
});
});
the code is running without any error, but the '#myNews' not getting affected when clicking the '#click1' link.
Need some help pls.
Thanks in advance
I'm the one behind ist-ui-panel, and Jesse was right — by now the only way for you is to use 'destroy' method somewhat like:
$(document).ready(function(){
$('#click1').bind({
'click': function() {
$('#myNews').panel('destroy');
$('#myNews').panel({
'collapsible' :true,
'collapseType':'slide-right',
'stackable':true
});
}
});
$('#click2').bind({
'click': function() {
$('#myNews').panel('destroy');
$('#myNews').panel({'collapsible': false});
}
});
});
Notice, you should explicitly destroy previous panel before making a new one.
If you read the uncompressed source code for that widget, it appears that what you are doing is only meant to be used to create panels, not to modify them afterward.
The underlying software is either buggy or I don't understand it. So you'll have to hunt down some bugs, but you can use the 'destroy' method on that widget to reset the div completely, and then make it a panel again, like so:
$('#myNews').panel("destroy");
$('#myNews').panel(...
As I said, it's buggy or I don't quite get it - there's an error raised by the destroy call which you have to catch, and subsequent calls to make new panels do make panels, but they aren't completely correct.

Resources