I am looking to use a good jquerymobile plugin for splitview.
I used asyraf9's plugin (http://asyraf9.github.io/jquerymobile-splitview/) for my old version, but latest version of jquerymobile isnt supported by the plugin.
Requirements-
Page should look like this
http://asyraf9.github.io/jquerymobile-splitview/
Should show only the left content on iPhone, and show left & right on ipad
When in iPad view, it should show only left part, and navigate from Left -> right on click of a list item.
I can't use Panel to create splitview, as I'm already using a panel for slide menu.
Is there any exisiting plugin that I can use with JQM 1.3+ ?
Note - Similar question (asked by someone else) was marked as duplicate - https://stackoverflow.com/questions/19504645/any-solutions-out-there-for-splitview-in-jquery-mobile-1-3-x . I am aware of cocepts like floating and media queries, but need a plugin that handles javascript to navigate to Right side content in iPhone.
Thanks in advance ..
I ended up writing custom code to achieve this.
When in iPad view, it issues an AJAX get request to update div on the Right.
When in iPhone, it navigates to a different page when clicking an item on the left.
#media all and (min-width: 0px) and (max-width: 800px) {
.leftsidePart
{
clear:both;
width:100%;
}
.rightsidePart
{
display:none;
}
}
#media all and (min-width:800px){
.leftsidePart
{
float:left;
width:30%;
}
.rightsidePart
{
float:right;
width:65%;
}
}
Related
I have a fixed button for a CTA (call to action) at the bottom of my web page. Scrolling down the page on newer version of iOS, mobile Safari hides the bottom navigation bar (with back, forward, share, bookmark, and new tab buttons). If you click on the CTA button, instead of executing that action, mobile Safari shows the bottom nav bar.
As a solution, I was looking to alway force-show the bottom nav bar. Is there a way of doing this? Both Jack Threads when viewed on mobile, and Thread Flip's mobile site are able to pull this off when viewing an individual item.
I'm unable to reverse engineer this so far. Does anyone know how the force-show is accomplished?
Related to:
Buttons aligned to bottom of page conflict with mobile Safari's menu bar and
Prevent Mobile Safari from presenting toolbar when bottom of viewport is tapped
I think I may have found an answer. Setting your content to have the following styles:
height: 100% (allows content to fill the viewport and go beyond the
bottom)
overflow-y: scroll (allows you to scroll below the viewport;
the default value is visible)
-webkit-overflow-scrolling: touch (to smooth any scroll behavior)
appears to force the iOS menu in Safari to always appear. That way, button clicks will actually work instead of opening up the Safari menu.
Unfortunately, you have to pair this CSS with JavaScript browser detection because it messes up the scrolling on iOS Chrome (also webkit). There's no way to target all versions of iOS Safari only using only CSS.
My answer is, don't try.
Whilst Jon Catmull's answer technically does force the browser to retain the bottom toolbar. In trials I've experienced a massive performance drop following that setup.
An example of this is with https://www.contiki.com/uk/en, the toolbar appears permanently but the performance loss is noticeable between Chrome and Safari.
After investigating other websites it seems that the world has just accepted that this double-click is a necessary evil.
https://www.bbc.co.uk/news, breaking news appears at the bottom of the browser, if the ui is minimised, the first click returns the bottom toolbar, the second click goes through to the article.
amazon, ebay etc the toolbar is minimised as per the browser defaults. Any clicks to links in the bottom ~30 pixels enable the toolbar.
Whilst there are technical solutions in other answers here, I don't think the double click compares to the performance loss
I'm pasting in a solution mentioned at https://benfrain.com/the-ios-safari-menu-bar-is-hostile-to-web-apps-discuss/#comment-119538 in relation to how this is done for https://app.ft.com:
The trick was adding height: 100% to html, and body, and anywhere in
the css where it was using 100vh. No js browser detection needed as it
causes no quirks in iOS Chrome, Safari fullscreen, or on Android
browsers.
I'm having this same issue. We're working to implement a bottom navigation on our site and safari is giving us problems because tapping the bottom of the screen opens Safari's bottom nav, forcing users to click twice. The best solution we've come up with has been to add a 44px space below the navigation which looks really bad. It would be nice if I could force safari's navigation to stay open so it could fill that space instead of an essentially useless empty block.
I believe the height: 100% is the way to go. It seems this seems to make Safari think that it might as well show the bar as no content is trying to go behind it, and then you add scroll within you 100% height element.
My issue was different as my button was in a fixed position modal, I didn't want the Safari bottom nav to show all the time but when my mobile filter nav opened it needed to be shown.
Essentially applying the code below (e.g. on menu-open class). and then positioning menu as position: fixed and height: 100%
html.menu-open {
height: 100%;
body {
position: fixed;
width: 100%;
top: 0px;
overflow: hidden;
}
}
.menu {
position: fixed;
height: 100%;
width: 100%;
overflow: auto;
}
working example here:
https://www.electronicsadvisor.com/products/51/washing-machines-tumble-dryers
Open link
scroll down to hide safari bottom nav
click the filters button near the top of screen
The Filter menu will open and force the safari nav open.
Screenshots from example:
Before the filter button clicked:
Then when opening nav with js I apply styles above and the nav is forced open
Theres a better solution to this problem(i think). I check the windows's innerHeight on pageload. On scroll, if the height increases at least 50px, i can raise the button 25px. 25px appears to be the sweet-spot for this, you need to touch the very bottom of the button to show the toolbar. Here is a live demo and the code: https://visztpeter.me/demos/ios.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Fix tap for button at the bottom in iOS Safari when the toolbar is gone</title>
<style type="text/css">
div {
margin:20px;
height:2000px;
background:gray
}
button {
position:fixed;
bottom:0;
left:0;
right:0;
height:48px;
background:blue;
border:none;
transition: all ease 0.2s;
}
.ios-toolbar-gone button {
transform: translateY(-25px);
}
</style>
</head>
<body>
<div></div>
<button></button>
<script>
var baseWindowHeight = Math.max(window.innerHeight);
var classAdded = false;
var documentBody = document.body;
document.addEventListener('scroll', function(e){
var newWindowHeight = Math.max(window.innerHeight);
if(newWindowHeight-50 > baseWindowHeight) {
if (! documentBody.classList.contains("ios-toolbar-gone")) {
documentBody.classList.add("ios-toolbar-gone");
}
} else {
if (documentBody.classList.contains("ios-toolbar-gone")) {
documentBody.classList.remove("ios-toolbar-gone");
}
}
});
</script>
</body>
</html>
I have a registration function in a web application that takes a user through a four-step process to add information to the site. When a user clicks the 'Add' button, a Bootstrap modal appears and the user starts on step #1.
Each step has a menu of options for a user to choose from and the data that is populated in each step is dependent on the previous steps' choices. A user can leave a step blank and continue, but then they have no choices to make for the rest of the process. This functionality is behaving as expected in every desktop and mobile browser except for Safari on iPad.
In Safari, the user will open the modal, choose data in step 1, and move to step 2. If the user does not choose anything in this dropdown they can continue to step 3. However, if they do make a choice in step 2, the modal disappears and the user cannot continue. This only happens in Safari for iPad/iPhone.
I have tried setting up the web inspector on the iPad and loading the console on a Mac, but there are no errors or other messages of use in the console. I'm trying to figure out if this is a bug in Safari, or if Safari handles modal inputs from a select tag differently than other browsers.
Had a developer friend take a look. He added this function:
jQuery.usingSafari = function(allowDevices){
allowDevices = allowDevices != undefined ? allowDevices : true;
if(!allowDevices){
return /iPhone|iPad|iPod|Safari/i.test(navigator.userAgent)
&& navigator.userAgent.indexOf('Chrome') == -1
&& navigator.userAgent.indexOf('iPhone') == -1
&& navigator.userAgent.indexOf('iPad') == -1
&& navigator.userAgent.indexOf('iPod') == -1;
} else{
var results = /iPhone|iPad|iPod|Safari/i.test(navigator.userAgent) && navigator.userAgent.indexOf('Chrome') == -1;
return results;
}
}
//Disable backdrop
if(jQuery.usingSafari(false)) {
document.write('<style>div.modal-backdrop{ display:none; }</style>');
}
And then the modal call:
jQuery('#player-lightbox').modal({
backdrop: jQuery.usingSafari(true) ? "static" : true,
show:true}
);
This seems to have fixed the problem. Hope this helps others!
This seems to be caused by the fade transition. I first detected if the app runs on iOS, then made a query for .modal elements and removed class fade. This resolved the issue both on iPad/iPhone. Note: Modal backdrop might need some extra effort to make that play nice with the virtual keyboard popping in and out.
To illustrate:
if(isIOS())
$('.modal').removeClass('fade');
Edit: iPad (horizontal) also required
$('.modal').on('shown.bs.modal', function () {
$(this).find('.modal-backdrop').css('position', 'absolute');
});
I had a similar issue with a droplist inside a container that was disappearing upon making a selection and this was ONLY happening on a actual IPAD device (checking in chrome w/ the device toolbar with 'IPAD' selected worked fine). This seems to be a known bug as mentioned in the comment above.
Changing the css for the container to position: absolute resolved the issue for me. However it would break the layout for other devices & viewports.
The fix was to target only IPADs with the modified css rule:
#media all and (device-width: 768px) and (device-height: 1024px) and (orientation:portrait) {
.your-container {
position: absolute;
}
}
#media all and (device-width: 768px) and (device-height: 1024px) and (orientation:landscape) {
.your-container {
position: absolute;
}
}
I am having some trouble with this and haven't found a solution.
The solutions I find are for background-size:cover; when applying to a whole page, whereas I am using this on a specific div.
First, the site is http://www.sexypizzamarketing.com.
If you check this site, there is a DIV with a background-size:cover for an image, and here is the css:
#div3 {
margin-top:40px;
background-image:url("images/Desert.jpg");
-webkit-background-size:cover;
-moz-background-size:cover;
-o-background-size:cover;
background-size:100%;
background-repeat:no-repeat;
background-attachment:fixed;
background-color:#914211;
color:#201E1E;
background-color:#A4FFEE;
height:600px;
}
so as you scroll down, this 600px div moves over a fixed image. all of the research I've done is talking about how this background-position:fixed does not work on mobile. but when ive tested this on my android phone and a windows phone (and all browsers on PC) this has worked.
so really, unless you have an iphone, you won't be able to see this problem. ive used testmobile.me to test iphone, and it does not show up there. This is driving me crazy, because until now, I've been editing the live site, then asking someone to screenshot the site and send it to me... yea. 1. does any one know how to solve this?
So next, I decided to scrap this on iphones, would get rid of it for iphones. so I included this in css,
#media only screen and (max-width: 700px), only screen and (max-device-width: 700px) {
/* CSS overrides for mobile here */
#div3 {
background-color:black;
height:500px;
background-image:url("images/Background.jpg");
}
and this isn't hasn't solved it either.
**EDIT. this makes sense, but I didnt realize it. I put the #media only css to specify device width for a specific div (div3) above the regular div3 css, so it wasn't overriding. I moved it to the bottom of the section, allowing the #media to override the div3 css, so this solved that. A few things- this targets all media devices max width:700px, not just iphones. so i will look into that (because the site worked fine on windows and android phone)
As soon as I get the spare iphone and figure out how to connect it to localhost, then I will try the suggestions from alexander, because I don't want to risk messing something up by editing the live site through cpanel.
I'll be getting an old iphone for testing purposes as well.
but any suggestions, or if you can point me in the right direction, I'll make you some shrimp tacos or something.
How can I make the side panel content scrollable in case there are many items, without scrolling the content on the main page (in JQM 1.3 Beta)? I am trying to implement this for an application running on both Desktop and Mobile browsers.Have looked everywhere, but cannot find the answer.
I've made a div inside the panel that is scrollable, but this doesn't work on iOS4 and below without 2-finger scrolling (div within div issue in iOS).
Please, visit the following to find the answer to the above question:
JQM 1.3 panel + iscrollview + dynamically loaded
http://forum.jquery.com/topic/jqm-1-3-panel-iscrollview-dynamically-loaded-pages
jquery-mobile-iscrollview
https://github.com/watusi/jquery-mobile-iscrollview
.ui-panel-inner .ui-content myElement {
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
You can make the selector more specific to a given element or just leave the "ui-panel-inner" if you want the whole side panel to be scrollable.
Note: The "-webkit-overflow-scrolling: touch" adds native inertia scrolling to the overflow and is not needed if all you want is scroll functionality. This should work on webkit browsers; mobile safari and chrome. But I have only tested it on mobile safari. It will not work on mobile IE but again, I have not tested it.
I have some css menus on my site that expand with :hover (without js)
This works in a semi-broken way on iDevices, for example a tap will activate the :hover rule and expand the menu, but then tapping elsewhere doesn't remove the :hover. Also if there is a link inside the element that is :hover'ed, you have to tap twice to activate the link (first tap triggers :hover, second tap triggers link).
I've been able to make things work nicely on iphone by binding the touchstart event.
The problem is that sometimes mobile safari still chooses to trigger the :hover rule from the css instead of my touchstart events!
I know this is the problem because when I disable all the :hover rules manually in the css, mobile safari works great (but regular browsers obviously don't anymore).
Is there a way to dynamically "cancel" :hover rules for certain elements when the user is on mobile safari?
See and compare iOS behavior here: http://jsfiddle.net/74s35/3/
Note: that only some css properties trigger the two-click behavior, e.g. display:none; but not background: red; or text-decoration: underline;
I found that ":hover" is unpredictable in iPhone/iPad Safari. Sometimes tap on element make that element ":hover", while sometimes it drifts to other elements.
For the time being, I just have a "no-touch" class at body.
<body class="yui3-skin-sam no-touch">
...
</body>
And have all CSS rules with ":hover" below ".no-touch":
.no-touch my:hover{
color: red;
}
Somewhere in the page, I have javascript to remove no-touch class from body.
if ('ontouchstart' in document) {
Y.one('body').removeClass('no-touch');
}
This doesn't look perfect, but it works anyway.
:hover isn't the issue here. Safari for iOS follows a very odd rule. It fires mouseover and mousemove first; if anything is changed during these events, 'click' and related events don't get fired:
mouseenter and mouseleave appear to be included, though they're not specified in the chart.
If you modify anything as a result of these events, click events won't get fired. That includes something higher up in the DOM tree. For example, this will prevent single clicks from working on your website with jQuery:
$(window).on('mousemove', function() {
$('body').attr('rel', Math.random());
});
Edit: For clarification, jQuery's hover event includes mouseenter and mouseleave. These will both prevent click if content is changed.
A better solution, without any JS, css class and viewport check: you can use Interaction Media Features (Media Queries Level 4)
Like this:
#media (hover) {
// properties
my:hover {
color: red;
}
}
iOS Safari supports it
More about:
https://www.jonathanfielding.com/an-introduction-to-interaction-media-features/
The browser feature detection library Modernizer includes a check for touch events.
It’s default behavior is to apply classes to your html element for each feature being detected. You can then use these classes to style your document.
If touch events are not enabled Modernizr can add a class of no-touch:
<html class="no-touch">
And then scope your hover styles with this class:
.no-touch a:hover { /* hover styles here */ }
You can download a custom Modernizr build to include as few or as many feature detections as you need.
Here's an example of some classes that may be applied:
<html class="js no-touch postmessage history multiplebgs
boxshadow opacity cssanimations csscolumns cssgradients
csstransforms csstransitions fontface localstorage sessionstorage
svg inlinesvg no-blobbuilder blob bloburls download formdata">
Some devices (as others have said) have both touch and mouse events. The Microsoft Surface for example has a touch screen, a trackpad AND a stylus which actually raises hover events when it is hovered above the screen.
Any solution that disables :hover based on the presence of 'touch' events will also affect Surface users (and many other similar devices). Many new laptops are touch and will respond to touch events - so disabling hovering is a really bad practice.
This is a bug in Safari, there's absolutely no justification for this terrible behavior. I refuse to sabotage non iOS browsers because of a bug in iOS Safari which has apparently been there for years. I really hope they fix this for iOS8 next week but in the meantime....
My solution:
Some have suggested using Modernizr already, well Modernizr allows you to create your own tests. What I'm basically doing here is 'abstracting' the idea of a browser that supports :hover into a Modernizr test that I can use throughout my code without hardcoding if (iOS) throughout.
Modernizr.addTest('workinghover', function ()
{
// Safari doesn't 'announce' to the world that it behaves badly with :hover
// so we have to check the userAgent
return navigator.userAgent.match(/(iPad|iPhone|iPod)/g) ? false : true;
});
Then the css becomes something like this
html.workinghover .rollover:hover
{
// rollover css
}
Only on iOS will this test fail and disable rollover.
The best part of such abstraction is that if I find it breaks on a certain android or if it's fixed in iOS9 then I can just modify the test.
Adding the FastClick library to your page will cause all taps on a mobile device to be turned into click events (regardless of where the user clicks), so it should also fix the hover issue on mobile devices. I edited your fiddle as an example: http://jsfiddle.net/FvACN/8/.
Just include the fastclick.min.js lib on your page, and activate via:
FastClick.attach(document.body);
As a side benefit, it will also remove the annoying 300ms onClick delay that mobile devices suffer from.
There are a couple of minor consequences to using FastClick that may or may not matter for your site:
If you tap somewhere on the page, scroll up, scroll back down, and then release your finger on the exact same position that you initially placed it, FastClick will interpret that as a "click", even though it's obviously not. At least that's how it works in the version of FastClick that I'm currently using (1.0.0). Someone may have fixed the issue since that version.
FastClick removes the ability for someone to "double click".
There are basically three scenarios:
User only has a mouse/pointer device and can activate :hover
User only has a touchscreen, and can not activate :hover elements
User has both a touchscreen and a pointer device
The originally accepted answer works great if only the first two scenarios are possible, where a user has either pointer or touchscreen. This was common when the OP asked the question 4 years ago. Several users have pointed out that Windows 8 and Surface devices are making the third scenario more likely.
The iOS solution to the problem of not being able to hover on touchscreen devices (as detailed by #Zenexer) is clever, but can cause straightforward code to misbehave (as noted by the OP). Disabling hover only for touchscreen devices means that you will still need to code a touchscreen friendly alternative. Detecting when a user has both pointer and touchscreen further muddies the waters (as explained by #Simon_Weaver).
At this point, the safest solution is to avoid using :hover as the only way a user can interact with your website. Hover effects are a good way of indicating that a link or button is actionable, but a user should not be required to hover an element to perform an action on your website.
Re-thinking “hover” functionality with touchscreens in mind has a good discussion about alternative UX approaches. The solutions provided by the answer there include:
Replacing hover menus with direct actions (always visible links)
Replacing on-hover menus with on-tap menus
Moving large amounts of on-hover content into a separate page
Moving forward, this will probably be the best solution for all new projects. The accepted answer is probably the second best solution, but be sure to account for devices that also have pointer devices. Be careful not to eliminate functionality when a device has a touchscreen just to work around iOS's :hover hack.
The JQuery version
in your .css use
.no-touch .my-element:hover
for all your hover rules
include JQuery and the following script
function removeHoverState(){
$("body").removeClass("no-touch");
}
Then in body tag add
class="no-touch" ontouchstart="removeHoverState()"
as soon as the ontouchstart fires the class for all hover states is removed
I agree disabling hover for touch is the way to go.
However, to save yourself the trouble of re-writing your css, just wrap any :hover items in #supports not (-webkit-overflow-scrolling: touch) {}
.hover, .hover-iOS {
display:inline-block;
font-family:arial;
background:red;
color:white;
padding:5px;
}
.hover:hover {
cursor:pointer;
background:green;
}
.hover-iOS {
background:grey;
}
#supports not (-webkit-overflow-scrolling: touch) {
.hover-iOS:hover {
cursor:pointer;
background:blue;
}
}
<input type="text" class="hover" placeholder="Hover over me" />
<input type="text" class="hover-iOS" placeholder="Hover over me (iOS)" />
Instead of only having hover effects when touch is not available I created a system for handling touch events and that has solved the problem for me. First, I defined an object for testing for "tap" (equivalent to "click") events.
touchTester =
{
touchStarted: false
,moveLimit: 5
,moveCount: null
,isSupported: 'ontouchend' in document
,isTap: function(event)
{
if (!this.isSupported) {
return true;
}
switch (event.originalEvent.type) {
case 'touchstart':
this.touchStarted = true;
this.moveCount = 0;
return false;
case 'touchmove':
this.moveCount++;
this.touchStarted = (this.moveCount <= this.moveLimit);
return false;
case 'touchend':
var isTap = this.touchStarted;
this.touchStarted = false;
return isTap;
default:
return true;
}
}
};
Then, in my event handler I do something like the following:
$('#nav').on('click touchstart touchmove touchend', 'ul > li > a'
,function handleClick(event) {
if (!touchTester.isTap(event)) {
return true;
}
// touch was click or touch equivalent
// nromal handling goes here.
});
Thanks #Morgan Cheng for the answer, however I've slightly modified the JS function for getting the "touchstart" (code taken from #Timothy Perez answer), though, you need jQuery 1.7+ for this
$(document).on({ 'touchstart' : function(){
//do whatever you want here
} });
Given the response provided by Zenexer, a pattern that requires no additional HTML tags is:
jQuery('a').on('mouseover', function(event) {
event.preventDefault();
// Show and hide your drop down nav or other elem
});
jQuery('a').on('click', function(event) {
if (jQuery(event.target).children('.dropdown').is(':visible') {
// Hide your dropdown nav here to unstick
}
});
This method fires off the mouseover first, the click second.
For those with common use case of disabling :hover events on iOS Safari, the simplest way is to use a min-width media query for your :hover events which stays above the screen width of the devices you are avoiding. Example:
#media only screen and (min-width: 1024px) {
.my-div:hover { // will only work on devices larger than iOS touch-enabled devices. Will still work on touch-enabled PCs etc.
background-color: red;
}
}
For someone still looking for a solution if none of the above worked,
Try this,
#media (hover: hover)
{
.Link:hover
{
color:#00d8fe;
}
}
This hover pseudo will only be applied for devices with pointers and works normal on touch devices with just .active classes.
Just look at the screen size....
#media (min-width: 550px) {
.menu ul li:hover > ul {
display: block;
}
}
heres the code you'll want to place it in
// a function to parse the user agent string; useful for
// detecting lots of browsers, not just the iPad.
function checkUserAgent(vs) {
var pattern = new RegExp(vs, 'i');
return !!pattern.test(navigator.userAgent);
}
if ( checkUserAgent('iPad') ) {
// iPad specific stuff here
}