I just recently started working with jQuery Mobile. I ran into a issue that I don't get quite yet.
I got this code. What it does is that it triggers the toggle twice. One for jQuery and the other for jQuery Mobile (works as expected when removing reference to jQM). Any ideas on how to avoid this for use with Mobile? Adding namespace...?
var navigation = $main_nav.find("[data-toggle-id='" + target + "']");
navigation.toggle(200, function() {
console.log('toogle');
});
EDIT
Demo: http://jsfiddle.net/4mpdR/4/
I don't get the same behaviour here but this is basically my setup.
Edit2
$(function () {
$(document).on('click', '.nav__toggle', function () {
var $main_nav = $('.main-nav');
var target = $(this).data('target');
var navigation = $main_nav.find("[data-toggle-id='" + target + "']");
navigation.toggle(200, function() {
console.log('toogle');
});
});
});
Edit3
It's just a <nav>. looking in the console I see that it triggers twice and one time it has the reference to my actual .js file, second is the VM[number], removing jQuery Mobile eliminates the VM.
[nav.main-nav__collapse.clearfix, prevObject: jQuery.fn.jQuery.init[1], context: document, selector: ".main-nav [data-toggle-id='main-nav__collapse']", constructor: function, init: function…]
0: nav.main-nav__collapse.clearfix
context: document
length: 1
prevObject: jQuery.fn.jQuery.init[1]
selector: ".main-nav [data-toggle-id='main-nav__collapse']"
__proto__: Object[0]
First you find out user agent(iphone,android,blackberry,webos) then you can separate the event of different platform
$.browser.device = (/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase()));
now $.browser will return "device" for all above devices
Related
I'm using hammer.js for gesture functionality on my web application. I have used it to swipe a video element and it works perfect as expected. However, when I apply the following code to an image element it's not working.
App.Views.Photo = Backbone.View.extend({
template : template('photoTemplate'),
className : 'photo',
parent : null,
events: {
'swipe' : 'swiped',
// 'pan' : 'dragged'
},
...
swiped: function(e) {
this.remove();
this.parent.newContent(this.model);
},
This exact same code is working for the video elements but not for the images. I also tried doing e.gesture.preventDefault(); inside the swiped function but that didn't work either. I'm testing the application on firefox at the moment.
Any help will be appreciated.
Thanks
[EDIT]: I'm initializing the hammer code as follows
render: function() {
$(this.el).attr('id', this.model.attributes._id);
this.$el.html( this.template( this.model.toJSON() ) );
this.$el.hammer();
return this;
},
You can use:
<img draggable="false"...
Or in CSS like this (May not be supported by all browsers, esp IE)
pointer-events: none;
Ok, so after banging my head on this problem for weeks I finally got the answer.
in the initialize function I placed the following code
$('img').on('dragstart', function(event) { event.preventDefault(); });
So it looks like this
initialize: function(opts) {
this.render();
this.parent = opts.parent;
$('img').on('dragstart', function(event) { event.preventDefault(); });
},
What this does is that it prevents the image from being dragged like default and that did the trick.
And now on swipe the image gets removed like I wanted.
[EDIT]
If you have multiple images on the page add this to the event like
this.$('img').on('dragstart', function(event) { event.preventDefault(); });
This will apply to all of the picture that are rendered with that view.
I am currently learning JavaScript using O'Reilly's "Learning Web Application Development". In the example, we are constructing a website using HTML and CSS, which includes 3 tabs which should be able to be selected and become the "active" tab. The books claims that the following two ways of writing the tab code are equivalent:
1)
var main = function() {
"use strict";
var tabNumber;
for (tabNumber=1;tabNumber<=3;tabNumber++) {
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
$(tabSelector).on("click",function() {
$(".tabs span").removeClass("active");
$(tabSelector).addClass("active");
$("main .content").empty();
return false;
});
}
}
$(document).ready(main);
2)
var main = function() {
"use strict";
$(".tabs a span").toArray().forEach(function(element) {
$(element).on("click", function() {
console.print("this element: " + element);
$(".tabs span").removeClass("active");
$(element).addClass("active");
$("main .content").empty();
return false;
});
});
}
$(document).ready(main);
However, they do not output the same result. The version using forEach works correctly, so that when I click one of the tabs the attention moves to that tab and it becomes highlighted. However, in the version using a for loop, whenever I click any tab, the attention always moves to the last tab. To confirm what is happening, I printed out the name of the element inside the event listener with both methods, using 3 tabs total. And using the for loop, no matter which tab I click I am getting a response of
"this element: .tabs a:nth-child(3) span"
Could someone please help me explain why this is happening? Why is the output different using for or forEach? And why, using for, is it always passing the last element of tabs to the event listener?
Looks like there's a problem here:
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
$tabSelector.on("click",function(){
You've created a variable that doesn't have the $ at the beginning, then attached the event to a variable (not sure what it would refer to) with a $ at the beginning.
It should be changed to this, I believe:
$(tabSelector).on("click",function(){
In the for loop solution, you are setting tabSelector multiple times like so:
var tabSelector = ".tabs a:nth-child("+tabNumber+") span";
This selector is, in the end, going to be set to the last tabNumber, which is always going to be called when you make a reference to it:
$(tabSelector).addClass("active");
To avoid that, replace it by this, which will be different for each of them:
$(this).addClass("active");
JS Fiddle Demo
I'm using classed links to change FlowPlayer content. Here is a working version: http://jsfiddle.net/r9fAj/
In my actual page using the same code the first link clicked works fine. The second one does not fire the click function at all. Even if I comment out everything but the console.log()...
$('.playerLink').click( function() {
audioPlayer.unload();
initAudioPlayer();
$('#player').css('display', 'block');
$('#player').animate({"height":"50px"}, 1000);
var newClip = {'url':$(this).attr('ajax-data'),'autoplay':true};
audioPlayer.play(newClip);
console.log('playing ' + $(this).attr('ajax-data'));
});
HTML like so
Listen
Listen
<a id="flowplayer" href="/audio/episodes/09_27_2013_Happy_Hour_88509726.mp3"></a>
And the player initialized like so:
var audioPlayer;
var initAudioPlayer = function () {
$f("flowplayer", "/player/flowplayer-3.2.16.swf", {
plugins: {
controls: {
fullscreen: false,
autoHide: false,
}
},
clip: {
autoPlay: false,
url: "",
}
});
audioPlayer = $f();
};
initAudioPlayer();
Since the jsFiddle works over and over I assume something else in my page is preventing the second click() from working but the console has no errors for me.
So my question is, short of posting the whole site's code how do I pursue debugging this?
So it sounds like your .click() event handler is only being fired for the first link you click and not for additional clicks. For general debugging, you could take your page that is not working and gradually comment out / remove other part of the JS and HTML until you are able to make it work correctly. Or start with the minimal amount that is working (the fiddle) and gradually add in the rest to see when it stops working.
So this is the first site I have done where content is delivered via AJAX and internal links are caught by
$("a:not([href^='http://'])").click( function(e) {
var url = $(this).attr("href");
var title = ($(this).attr("title")) ? ': ' + $(this).attr("title") : '';
e.preventDefault();
if(url!=window.location){
window.history.pushState({path:url},title,url);
$('#contentMain').load(url);
document.title = "It's New Orleans" + title;
}
});
For some reason it does work once to click a link with the class but the second time gets preventDefault()ed.
Listen
The fix was adding [href^='#'] to not() e.g.
$("a:not([href^='http://'],[href^='#'])").click( function(e) {
I have a few location attrs on my website for a few dynamic drop downs and clickable divs. While testing I saw that they are not working on any ipads or iphones. Is there a reason for this?
They look like this
$('.storyClick').click(function () {
var context = $(this).closest('.storyClick'),
story_id = context.find('.story_id').val();
$(location).attr('href', '/chapters/' + story_id)
});
The updated code? Sure...
$('.storyClick').click(function () {
var context = $(this).closest('.storyClick'),
story_id = context.find('.story_id').val();
location.href = '/chapters/' + story_id;
});
Why are you making a jQuery object out of that?
location.href = '/chapters/' + story_id;
DOM nodes are the only things that should be wrapped in a jQuery object. (Well, ideally, nothing would be, but here we are.)
And you apparently need to handle two events using .on('click touchstart', …), because it’s not a link.
I'm developing a tablet application with the jquery.mobile-1.0rc3 version. Previoulsy, I used the jquery.mobile-1.0a4.1 version on another application, and it was possible to refresh a listview by doing myListview.listview( "refresh" ).
I'm having some problems doing the same with the new jquery.mobile-1.0rc3 version. Is it possible to do that with the new jquery.mobile-1.0rc3 version?
Thank you very much.
Here's a bit of the code:
var lists = $( '#posicaoIntegradaActivosList, #posicaoIntegradaPassivosList, #posicaoIntegradaOutrosList' );
lists.empty();
/* Fill the lists with jquery template */
lists.listview( "refresh" );
Error:
uncaught exception: cannot call methods on listview prior to
initialization; attempted to call method 'refresh'
Depending on when your code runs it may be running before the jQuery Mobile initialization process. jsFiddle by default runs code after the load event fires so the DOM is all setup and jQuery Mobile has done its initialization. If you change #Phill Pafford's jsFiddle (http://jsfiddle.net/qSmJq/3/) to run on "no wrap (body)" rather than "onLoad" then you get the same error you are reporting. So I recommend either removing the lists.listview('refresh'); line or putting your code inside either a document.ready or a pageshow/pagecreate event handler:
var lists = $( '#posicaoIntegradaActivosList, #posicaoIntegradaPassivosList, #posicaoIntegradaOutrosList' );
lists.empty();
/* Fill the lists with jquery template */
//lists.listview( "refresh" );
Here's a jsfiddle for running the code as soon as it is parsed by the browser: http://jsfiddle.net/jasper/qSmJq/5/
Or:
$(function () {
var lists = $( '#posicaoIntegradaActivosList, #posicaoIntegradaPassivosList, #posicaoIntegradaOutrosList' );
lists.empty();
/* Fill the lists with jquery template */
lists.listview( "refresh" );
}
Here is a jsfiddle for wrapping your code in a document.ready event handler: http://jsfiddle.net/jasper/qSmJq/4/
Or:
$('#my-page-id').on('pagecreate', function () {
var lists = $( '#posicaoIntegradaActivosList, #posicaoIntegradaPassivosList, #posicaoIntegradaOutrosList' );
lists.empty();
/* Fill the lists with jquery template */
//lists.listview( "refresh" );
}
Here is a jsfiddle for using the pageshow event: http://jsfiddle.net/jasper/qSmJq/6/
And here is a jsfiddle for using the pagecreate event: http://jsfiddle.net/jasper/qSmJq/7/
On a side note: if you want to detect whether or not jQuery Mobile has initialized a certain element you can check for the jQuery Mobile specific classes on the element:
$(function () {
//cache lists
var lists = $( '#posicaoIntegradaActivosList, #posicaoIntegradaPassivosList, #posicaoIntegradaOutrosList' );
//iterate through the lists
lists.each(function (index, value) {
//cache this specific list
var $value = $(value);
/*add rows to this listview here*/
//check if the listview has been initialized by jQuery Mobile by checking for the existence of the `ui-listview` class
if ($value.hasClass('ui-listview')) {
//since the class was found, refresh the already initialized element
$value.listview('refresh');
} else {
//the class was not found, so initialize the widget
$value.trigger('create');
}
});
});