I'm using JQuery Mobile to create a tree by using nested collapsibles. As with any treeview, a parent may or may not have any children. In my current approach, collapsibles that have no children are still collapsible, alltough the collapsible part is empty as there are no children. This results in a very ugly UI. What I would like to have is a way of turning off the behaviour of expanding the collapsible, yet being able to turn it on on collapsibles that do have children.
I've already tried different solutions, like the one being discussed here. It uses a very simple piece of code to disable the collapsing effect:
$("#page").live('pageinit', function(event) {
$(".ui-collapsible[data-allow-collapse=false]").unbind("expand collapse");
});
But that solution has the opposite effect: he is looking for a non-collapsible section while I'm looking for a non-expandable section. Just editing the answerers jsFiddle page (which can be found here) to reverse the effect creates very strange effects.
I've updated that jsFiddle to show you what happens. You will notice that once you click on the last element in the collapsible-list (Section 4) it will automatically collapse all the above elements (except for the first element, as this one has the property data-allow-collapse set to false. This seems strange behaviour to me, as it collapses all elements while clicking on a different element.
Is there any way to fix that behaviour or should I take a completely different approach? All I basically want is a property like data-allow-to-expand, and if that is set to false nothing happens after clicking on that specific element. When set to true, it should expand as it would normally.
Related
It is simply possible to find all truly visible and clickable elements in the page using the document.elementFromPoint function. However, it returns null for elements outside of the viewport.
So, how to find all clickable and visible elements in the full page? The visible elements are not just limited to the styles. Just consider a container <div> which is now hidden behind all children elements. So, the parent <div> is not longer visible.
So, do you have any idea how it is possible to find all really visible elements in the page? In the example above, obviously “Parent <div>” is not visible practically. There are some other unpredictable situations where those elements may not be visible and the styles (display,visibility, etc.) may not indicate it.
My final intention: I want to check if an element is really visible and clickable for the end-user or not. As an example use case I want to find all possible zones a user may click on.
I think you've misunderstand the basics behind events in domApi.
there will be bubbles and captures in any event happened at the client.
you must have seen code like this document.addEventListener('click',function(){},false),that means to use bubble instead of capture to handle event.
so actually clickable dom element is related with whether or not DOMJs uses bubble or capture
I have a testbed with four simple content DIVS which I would like to change the position of when each of them is clicked. Link below.
http://christopherwynne.com/tattoo/
I have performed similar functions with other sites in the past, and I feel like I am missing something fundamental. I am still new to Java, and have always had issues getting anything to work initially.
Any help with this issue would be greatly appreciated.
Your jQuery click handlers are not quite right. You're using:
$("galleryWrap")
but it should actually be
$("#galleryWrap")
to select the element by its id.
Once you've selected them properly you can do something like add a class which will attach the left margin of 205 you want.
Likewise you have a few other places where you're not selecting the elements properly. If you try selecting elements with these commands in the console you'll see jQuery can't find them.
An example: a command like $('div') selects all <div>s on the page, whereas if you wrote $('#div') you would select all elements with id="div".
I am using a bootstrap popover on svg elements in D3. Multiple popovers can be open at any given time. What I would like to know is how to, on clicking on a popover at the back, to force it to move to the front i.e. being focused on?
Is there any way to increment the z-index of an individual popover to move it forward manually?
Thanks.
Edit:
I have managed to create a fiddle using the suggested answer. The problem arises that, with using the global variable, it increments the z-index correctly on the most forward popover, but after bringing one to the front I am not able to access the others i.e. to even click the ones behind...so the click handler is not even being called. I'm thinking there is some type of layering going on. For example: If you look at the children nodes and click on one (the link in the title of the popover), then click on another one to semi-overlap the first open one - click the one behind and it will move forward. Click the one that is now behind and nothing happens:
jsfiddle.net/Sim1/YME9j/9
Is there an alternative to incrementing the z-index to bring a popover forward without hampering interaction with those that are behind it?
You should be able to do this in a click handler:
element.on("click", function() {
d3.select(this).attr("z-index", d3.select(this).attr("z-index") + 1);
})
As #AmeliaBR pointed out, this won't really work if you have more than one popover though as the z-index is only incremented by one. In a case like this, you could have a global variable that keeps track of the maximum z-index and use that.
I have a requirement to disable selection on a web page for everything except input[type=text] elements.
This accepted answer to a similar question almost does the trick, but it doesn't disable selection for containers that contain input[type=text] elements. Therefore the user can still select by starting a drag operation from within one of these containers.
Is this even possible, i.e. is it possible to disable selection for a container element, while enabling it for child elements (specifically, child input=text elements).
#Pointy, "Why not just take out that first .not() call?"
Taking out the first .not call, will give:
$('body').not('input').disableSelection();
which, as pointed out in the linked question, will still disable everything on the page, including the input[type=text] elements.
#David Thomas, "Do you have a live demo ..."
I don't have a live demo, but it's fairly trivial. For example, a div with a bit of padding that contains an input[type=text] element. The result is:
With $('body').not('input').disableSelection(); selectiopn is disabled for all the page, including the input elements.
With $('body *').not(':has(input)').not('input').disableSelection(); selection is disabled for all elements that don't contain an input element. But it is possible to select the whole page by starting a drag operation from within a container that contains an input element.
Well, cinch up your suspenders and get ready for a really dirty hack.
Disclaimer:
I don't think this is a good way to do things. I simply wanted to tackle the challenge of getting the OP's desired functionality. If someone else can get this to work in a cleaner way, please post it.
After playing around with the disableSelection() function, it seemed that if a parent element had been disabled, all of its children would be unselectable as well (please correct me if I'm wrong). So, I decided that if you wanted everything to be unselectable except small parts, you could put all of your markup in one unselectable <div> and use absolute positioning to place selectable clones of your <input> tags (or any tag, really) on top of the unselectable ones. These clones would reside in a second <div> that was not disabled.
Here's an example of this idea: http://jsfiddle.net/pnCxE/2/.
Drawbacks:
Styling becomes a big headache. Any element that relies on a parent's style (i.e., position, size, colors, etc.) cannot be cloned since the clones reside in a separate place.
Forms become much harder to manage since (again) the clone isn't in the same place as the cloned element.
You have to deal with naming collisions since the clone will have the same ID as the cloned element. (It's doable; I just didn't want to code it since it would probably need specific attention by anyone that uses this idea)
So, while you can work around the selectable limitations, you might be better off just accepting the container selection. I would think long and hard before putting this code into a production environment.
I've found a solution that appears to do what I want, and would be interested in comments / improvements from jquery / javascript experts.
$(document).ready(function () {
$("body").disableSelection();
$("body").delegate('input[type=text],textarea', "focus", function () {
$("body").enableSelection();
});
$("body").delegate("input[type=text],textarea", "blur", function () {
$("body").disableSelection();
});
});
When a textbox (input[type=text] or textarea) has the focus, then dragging with the mouse only selects text within the textbox. Therefore it's "safe" to enable selection for the whole page while a textbox has focus (between focus and blur events).
There is a noticeable delay when tabbing between textboxes on IE8/9. It's not noticeable on Google Chrome, which I understand has a faster javascript engine. So I can live with the performance hit, especially since IE10 is going to have a faster javascript engine.
UPDATE
When using ASP.NET UpdatePanel, this needs to be modified to disable selection after each partial postback:
Sys.Application.add_load(function () {
$("body").disableSelection();
});
Try this, although it is same with what you're already using:
$('* :not(input)').disableSelection();
I don't get though why do you have to use entire body element and not narrow it down to text nodes (p, h[..], ul, ol etc.)
And I agree with #David Thomas - it would be easier to see a test page you're working on.
I have two elements (think of two buttons side by side). I dynamically toggle the class "focusd" to change the highlighted effect. However, there's a quirk it doesn't always get redrawn and/or inserted in the DOM. For example, if in chrome I do console.log, I see the class changes (I'm using removeClass/addClass in jquery). But if I go to the Elements tab in the inspector, it shows the classes from before (and in fact, I'm not seeing the redrawing reflecting the toggling of the classes.)
I tried setting the parent div to display none then back to block but that didn't work. It's a "one off" modale screen, so efficiency doesn't matter so I've resorted to this hack where I essentially copy the parent's innerhtml, remove and reinsert the element. Horrible!
// Not sure why I need this hack. But if I don't, the buttons don't seem to get redrawn
var htm = jQuery(".rdata_container").html(); // copy the innerhtml
jQuery(".rdata_container").empty(); // empty and then append back
jQuery(".rdata_container").append(htm);
This seems like a specific quirk that someone must have ran into (I hope). If so, I'd love to know why my changes aren't reflected.
EDIT
Code posted here:
http://jsfiddle.net/roblevintennis/JCZnf/
you can use setTimeout when you are doing the other operation on the element, so for example:
$elm.addClass('hide')
setTimeout(function(){
$elm.removeCalss('hide')
},0);
Or you could force a repaint like so:
$elm.addClass('hide')
$elm.scrollTop; // forces a repaint (might be expensive for large amount of items)
$elm.removeCalss('hide');
These tricks will force the browser to re-draw the change, because there are two things happening here and the browser logic just combines them into one, which isn't the desired behavior.
Not directly an answer to your question, but you can use jQuery's toggleClass function to simplify your code.
Here's an updated version that uses toggleClass() and jQuery 1.6 and AFAICT works fine.
http://jsfiddle.net/JCZnf/7/