I have created a list, which when a item is clicked, a popup is shown.
The problem starts when using the code on a mobile device (where the screen is relatively small). When a list item is hit, very often, also a button in the popop is hit.
What is the best way to deactivate the buttons until the user realizes the popup even did show?
Try the code here.
The HTML code:
<div data-role="page" id="kon">
<div data-role="content">
<ul data-role="listview" id="kon_list" data-icon="false">
</ul>
<div data-role="popup" id="contactMsgBox" data-transition="pop">
<div data-role="content" data-theme="d" class="ui-corner-bottom ui-content">
<h3 class="ui-title">Ansprechpartner kontaktieren</h3>
Anrufen <br />
E-Mail senden <br />
Abbrechen
</div>
</div>
</div>
</div>
The JS code:
kontakts = JSON.parse('[{"mail":"test#test.de",'+
'"name":"test test","ort":"Stuttgart","tel":"0123 1234-123"},{"mail":"test2#test.de",'+
'"name":"test2 test2","ort":"Lauf","tel":"0123 1234-123"}]');
var listHTML = "";
for(var i=0; i<kontakts.length; i++)
{
//set the menu item
listHTML = listHTML + "<li tel='"+kontakts[i].tel+
"' mail='"+kontakts[i].mail.toLowerCase()+"'><h3>" + kontakts[i].ort +
"</h3><p>" + kontakts[i].name + "<br />Telefon\t" + kontakts[i].tel +
"<br />E-Mail\t" + kontakts[i].mail.toLowerCase() + "</p></li>";
}
//set items and reload
$('#kon_list').html(listHTML);
$('#kon_list').listview('refresh');
//bind list items
$('#kon_list').children('li').bind('touchstart mousedown', function(e) {
//alert('Selected Tel=' + $(this).attr('tel') + 'Mail=' + $(this).attr('mail'));
$("#contactMsgBox").popup("open");
});
You could change
$('#kon_list').children('li').bind('touchstart mousedown', function(e) {
to
$('#kon_list').children('li').bind('vclick', function(e) {
That way the popup won't show until the user lifts his finger or releases the mouse button.
The problem is happening because mobile browsers wait approximately 300ms (apparently 500ms on samsung galaxy s2) from the time that you tap the button to fire the click event. This wait was causing both to be tapped, the item, and the popup button.
The solution is to stop the browser from waiting. This can be accomplished with the fastclick library
Related
I have a rather large slideshow type site. All the slides are on one html page so I can't use the browser back function. Each slide has a back button. I can't specifically specify where that back button should go because the slide show is non-linear. So I could arrive at any particular slide from any other slide. Is there a way of making a history array or anything that I could use for this back button that would function as a back button?
I should say, I am a beginner. I'm still learning javascript.
Edit: I forgot to mention that I'm trying to do this purely in javascript/html/css.
I've got the back button working in javascript, but only one step backwards. I just made it so each button clicked updates a variable with the current slide's ID. Then the back button just "points" to that variable. The problem is, it won't go back more than one step because once you go back once the variable is never updated to the ID that you just went back from. Hope that makes sense.
You can use the History API:
When jumps from slide #1 to #5, call history.pushState:
var stateObject = {page: "5"};
history.pushState(stateObject, "Slide #5", "#5");
When navigates back, simply call history.back(), and add a popstate listener to show the desired slide:
window.addEventListener("popstate", function(event) {
$(".page").hide();
$("#p" + event.state.page).show();
}
The event.state here is the stateObject you pushed when you call history.pushState. For example, when user navigates back to Slide #5, the event.state is {page: "5"}.
function jump() {
var target = this.getAttribute("data-value");
document.querySelector(".on").classList.remove("on");
document.getElementById("s"+target).classList.add("on");
var stateObject = {page: target};
history.pushState(stateObject, "Slide #" + target, "#" + target);
}
document.querySelectorAll(".jump").forEach(function(element) {
element.addEventListener("click", jump);
});
document.querySelector(".back").addEventListener("click", function() {
history.back();
});
window.addEventListener("popstate", function(event) {
if (event.state === null) {
// the first page has no stateObject
document.querySelector(".on").classList.remove("on");
document.getElementById("s1").classList.add("on");
} else if (typeof event.state.page !== "undefined") {
document.querySelector(".on").classList.remove("on");
document.getElementById("s" + event.state.page).classList.add("on");
}
});
.page {display: none;}
.page.on {display: block;}
<button class="back">Back</button>
<div class="page on" id="s1">
Slide #1
<div class="action">
<button class="jump" data-value="3">Go to #3</button>
</div>
</div>
<div class="page" id="s2">
Slide #2
<div class="action">
<button class="jump" data-value="1">Go to #1</button>
</div>
</div>
<div class="page" id="s3">
Slide #3
<div class="action">
<button class="jump" data-value="2">Go to #2</button>
</div>
</div>
See:
https://developer.mozilla.org/en-US/docs/Web/API/History_API
https://developer.mozilla.org/en-US/docs/Web/Events/popstate
Basically I am designing this mobile app using jQuery mobile. I am quite new, but I've tried different ways with no success. I am trying to write the code, so that when you click on a list view item, a panel opens with the selected listview h1 (that contains the title of the list item) and p (which holds the description text enter code here). This is my HTML:
<div data-role="panel" id="event-details" data-position="right" data-theme="b" data-display="overlay">
<h1>Hello World</h1>
</div>
<ol data-role="listview" id="show-events" data-theme="a" data-filter="true">
<li data-name="3A Cold-rooms & Aircons" class="ui-shadow" data-icon="my-right-white">
<a href="#event-details" class="events-list">
<img src="img/flower.png" class="listImage" alt="" />
<h2>3A Cold-rooms & Aircons</h2>
<p>Patio & Outdoor Furniture</p>
<p>GARDEN & OUTDOOR ROOMS</p>
</a>
</li>
There are various items in the listview.
$('#show-events').children('li').bind('click', function(e) {
var htxt='<h2>' + $(this).attr('data-name') + '</h2>';
var ptxt='<p>' + txt + '</p>';
var stringText =htxt+ptxt;
$("ol#plannerList").append('<li data-icon="false" class="libgPlanner ui-shadow">' + '<a class="planner-btn" href="#map-page">' + stringText + '</a>' + '</li>').listview('refresh');
}
});
I have a common JQM popup across multiple pages. From each page, the contents of popup are refreshed using the data from page. On the first load of the page I can see the refreshed contents on popup. However, when I load new data onto popup div, I still get the older data on popup widget.
If I examine the innerHTML of the popup, it gives me new contents but cannot see them on the popup.
Here is my example code:
<body>
<div id="common-popup">
<div id="data-popup" data-role="popup">';
<p>Name: N/A<p>
<p>DOB: N/A <p>
</div> <!--Popup div ends -->
</div>
<div data-role="page" id="page1">
<input type='text' id='p1_name' value=''>Name: </input>
<input type='text' id='p1_dob' value=''>DOB: </input>
<button class="update-data" id="b1"/>
Watch Data
</div>
<div data-role="page" id="page2">
<input type='text' id='p2_name'>Name: </input>
<input type='text' id='p2_dob'>DOB: </input>
<button class="update-data" id="b2"/>
Watch Data
</div>
</body>
<script type="text/javascript">
$('.update-data').on('vclick', function(){
var id = $(this).id;
id = id.split('');
var htm = '<div id="data-popup" data-role="popup">';
htm += '<p>Name: ' + $('#p' + id[1] + '_name').val() +'<p>';
htm += '<p>Name: ' + $('#p' + id[1] + '_name').val() +'<p>';
$('#common-popup').html(htm).trigger('create');
});
</script>
In the above code if I examine the innerHTML using:
console.log("Common Inner Html: " + document.getElementById('common-popup').innerHTML);
I can see the updated contents, however when I open the pupup, I still see the older contents. Please let me know how to refresh the contents on popup
JS Fiddle: http://jsfiddle.net/bhavik89/49QwL/1/
In the Fiddle I can only see the initial contents, they are not refreshed upon the update
Instead of putting the popup in a DIV, just leave it under the body. Then when recreating it, leave the top level DIV there and just replace the contents:
<div id="data-popup" data-role="popup" data-theme="a" >
<div >
<p>Name: N/A</p>
<p>DOB: N/A </p>
</div>
</div>
Make sure your link has data-rel="popup":
Watch Data
Give your update button some text so we can see the button:
<button class="update-data" id="b1" >Update</button>
With this in place initialize the popup on document ready and then on the update button click, replace the popup HTML, call enhanceWithin() and finally call popup("refresh") to update the popup widget:
$(function(){
$("#data-popup").enhanceWithin().popup();
});
$(document).on("pagecreate", "#page1", function(){
$('.update-data').on('vclick', function(){
var id = $(this).prop("id");
id = id.split('');
var htm = '<div>';
htm += '<p>Name: ' + $('#p' + id[1] + '_name').val() +'<p>';
htm += '<p>DOB: ' + $('#p' + id[1] + '_dob').val() +'<p>';
htm += '</div>';
$("#data-popup").html(htm).enhanceWithin().popup("refresh");
});
});
Here is a working DEMO
I am using dynamic div content and toggling between them on clicks, works well but is there a way to retain the last viewed div when the user clicks forward and backward on his browser? Thanks.
<script>
$(".settings").click(function() {
var id = this.id;
if ($("." + $(this).attr('rel')).css('display') == 'none') {
$('.n_tab').hide();
$('.p_tab').hide();
($("." + $(this).attr('rel')).show());
}
});
</script>
<div class="settings" rel="n_tab">
<div class="title info_2_Title">
Notifications</div>
</div>
<div class="settings" rel="p_tab">
<div class="title info_2_Title">
Privacy</div>
</div>
<div id="MasterContainer">
<div class="n_tab" style="display: none;"> the N DIV </div>
<div class="p_tab" style="display: none;"> the P DIV </div>
</div>
Try using a library like history.js to set that up. Internally it will use the pushState API, or fall back to url fragments if the browser doesn't support that.
You could try adding an id to each tab and appending that in an object or array each time a div is selected.
Define an array history = []; outside the click event and in your click event something like
history.push($(this).id);
If you wanted to keep more detailed data you could use a json object and append to it.
Thanks for the help guys, but after fiddling ard with History.js, I still couldn't get it to work, in the end I used a cookie to store the state and then check it when the page with dynamic div loads.
$(function() {
var x = $.cookie('tab_cookie');
($(x).show());
if (x == '.m_tab') {
var btn = document.getElementById('<%= btnLoadm.ClientID %>');
if (btn) btn.click();
}
});
I have built my first jQuery mobile image gallery, but I have a bug I can't seem to fix. When an image is tapped it pops up to full screen and to carousel all the images I can swipe the images or tap prev/next arrows.
Edit: The problem has changed slightly since I wrote this question, therefor I need to make a few changes in my question and my code.
The images now swipe to every other image, according to the order they are shown in the gallery. I'm dynamically adding a data-index to each image, but somehow the result is tabindex="0" for each image that pops up.
<body>
<!-- gallery content -->
<div data-role="content" id="pagecontent" class="gallerycontent">
<a href="#imgshow" data-transition="pop" data-rel="dialog">
<img src="../img/someimage.jpg" alt="someimage.jpg"/>
</a>
<!-- plus more unordered images -->
</div> <!--/content-->
</div><!-- /page -->
<!-- full screen image preview -->
<div data-role="dialog" id="imgshow" data-theme="d">
<div data-role="header" data-theme="d">
<div id="dialoghead"></div>
</div>
<div data-role="content" data-theme="d">
<center><div id="dialogcontent"></div></center>
</div>
<div data-role="footer">
<center>
Previous
Next
</center>
</div>
</div>
</body>
The 'on-touch' function and 'gonext' function in jquery.
//on-touch function
$('.gallerycontent img').bind('tap',function(event, ui){
var src = $(this).attr("src");
var alt = $(this).attr("alt");
$('#dialogcontent').empty().append('<img src="' + src + '" style="width:100%;"/>' );
$('#dialoghead').empty().append('<center><h2>' + alt + '</h2></center>' );
$(this).parent().addClass('selectedimg');
});
function gonext() {
var current = $('a.selectedimg');
if (current.hasClass('last')) {
var next = $('a.first')
} else {
var next = current.next();
}
var src = next.find('img').attr("src");
var alt = next.find('img').attr("alt");
next.addClass('selectedimg');
current.removeClass('selectedimg');
$('#dialogcontent').empty().append('<img src="' + src + '" style="width:100%;"/>' );
$('#dialoghead').empty().append('<center><h2>' + alt + '</h2></center>' );
}
Any thought or hints?
I think the problem might be that the selectedimg class isn't being removed when the popup is opened. Try adding this line
$('.selectedimg').removeClass('selectedimg');
just before the addClass line into this function, like this:
//on-touch function
$('.gallerycontent img').bind('tap',function(event, ui){
var src = $(this).attr("src");
var alt = $(this).attr("alt");
$('#dialogcontent').empty().append('<img src="' + src + '" style="width:100%;"/>' );
$('#dialoghead').empty().append('<center><h2>' + alt + '</h2></center>' );
$('.selectedimg').removeClass('selectedimg');
$(this).parent().addClass('selectedimg');
});