This is really the same question as this but I'm hoping somebody can answer it more thoroughly.
I'm trying to create a "mobile" and a "full" version of a site using two different js functions. I understand responsive design and I'm doing most of the changes through CSS but the two versions will need to have two different mutually exclusive js functions. Enquire.js allows the use of media queries and they do work well if the browser window is not resized. But if you resize the window from "full" to "mobile", the function full() in my example does not stop running despite my best (probably not very good) efforts below. The alerts are always correct however: "true" for full() and "false" for mobile(), the functions just seem to ignore the if statements. I'm okay with not using enquire if there's a better option.
js-decider.js
$(function() {
window['fullEnabled'];
window['mobileEnabled'];
enquire.register("screen and (min-width:680px)", {
match : function() {
window['fullEnabled'] = true;
window['mobileEnabled'] = false;
full();
}
}).register("screen and (max-width:679px)", {
match : function() {
window['fullEnabled'] = false;
window['mobileEnabled'] = true;
mobile();
}
}).listen();
});
full.js
function full() {
if (window['fullEnabled']==true) {
alert(window['fullEnabled']);
// do other stuff
}
}
mobile.js
function mobile() {
if (window['mobileEnabled']==true) {
alert(window['fullEnabled']);
// do other stuff
}
}
It looks like your media queries are causes the issue you have a cross over.
Try this instead:
enquire.register("screen and (max-width:679px)", {
match : function() {
//small screen
}
}).register("screen and (min-width:680px)", {
match : function() {
//large screen
}
}).listen();
Related
I am trying to eliminate the useless check in a function, needed check variable is assigned at start-up of the app, so I don't want to check for it each time.
I have a code like this:
btnClose.addEventListener('click', function(e) {
window.close()
if (appSettings.sendAnonymousStats) {
visitor.event("Application", "App has been closed.").send()
}
})
This is my first try to optimize it, so now it doesn't need to do a "if" check each time it's called;
let btnCloseEv = appSettings.sendAnonymousStats ? btnClose.addEventListener('click', function(e) {
window.close()
visitor.event("Application", "App has been closed.").send()
}) : btnClose.addEventListener('click', function(e) {
window.close()
})
I wonder if theoretically there are better ways to achieve what I am trying to achieve?
Removing a single if statement, especially considering it only occurs once per click will not effect running time at all.
However for the purpose of discussion say it was performance critical, like if it was attached to onmousemove, then you can adjust your second approach with a small change to reduce code redundancy.
let btnCloseEv = btnClose.addEventListener('click',
appSettings.sendAnonymousStats ?
function(e) {
window.close();
visitor.event("Application", "App has been closed.").send();
} : function(e) {
window.close();
}
)
This works because functions in JS are higher order functions, which means they treated as variables and can be passed around in the same way variables can be. For instance this would work if a and b were numbers, or functions, or any other type of variable.
var c = someBoolean ? a : b;
Say each function was a lot bigger and you wanted to use this approach yet things were becoming unreadable, it would be better to name each function and attach them like so:
function moreComplexFunc(e) {
window.close();
visitor.event("Application", "App has been closed.").send();
// More complex code
}
function simpleFunc(e) {
window.close();
}
let btnCloseEv = btnClose.addEventListener(
'click',
appSettings.sendAnonymousStats ? moreComplexFunc : simpleFunc
)
Now say that you noticed there was a lot of code duplication in moreComplexFunc and simpleFunc, you could go a step further, and separate the similar code into a 3rd function like so:
function commonFunc(e) {
window.close();
}
function func1(e) {
commonFunc(e);
visitor.event("Application", "App has been closed.").send();
// other code
}
function func2(e) {
commonFunc(e);
// other code
}
let btnCloseEv = btnClose.addEventListener(
'click',
appSettings.sendAnonymousStats ? func1 : func2
)
The opportunities in a language which supports Higher Order Functions are really endless.
Just in case the function was a little more complex, another approach would be to simply put it in an additional event handler:
let btnCloseEv = btnClose.addEventListener('click',
function(e) {
window.close();
/*
... more code ...
*/
}
)
if (appSettings.sendAnonymousStats) {
btnClose.addEventListener('click',
function(e) {
visitor.event("Application", "App has been closed.").send();
}
}
I want to toggle events based on width. for mobile only click event should work. for desktop hover event should work. while page loading my code working properly when resize my code is not working.
please help me why my code is not working. Thanks in advance
$(document).ready(function(){
function forDesktop(){
$(".popover-controls div").off('click');
$(".popover-controls div").on('hover');
$(".popover-controls div ").hover(function(e){
//popup show code
});
}
function forMobile(){
console.log("mobile");
$(".popover-controls div").off('hover');
$(".popover-controls div").on('click');
$(".popover-controls div").click(function(e){
//popop show
});
}
function process(){
$(window).width() > 600?forDesktop():forMobile();
}
$(window).resize(function(){
process()
});
process();
});
Its very simple, 1st you cant write this much of code for every event. We have to come up with very simple solution, here is how it works
1st check the width of the Page in JS and assign Desktop/Mobile Class on body :
function process(){
if( $(window).width() > 600){
$("body").removeClass("mobile").addClass("desktop");
}else{
$("body").removeClass("desktop").addClass("mobile");
}
}
$(window).resize(function(){
process()
});
Now, you have execute the command for hover and click:
$(document).on('mouseover', 'body.mobile .popover-controls div',function(e){
alert("hover");
});
$(document).on('click', 'body.desktop .popover-controls div',function(e){
alert("click");
console.log("click");
});
I Hope this will work for you. :)
Check the Js fiddle Example: http://jsfiddle.net/asadalikanwal/xcj8p590/
I have just created for you, also i have modified my code
You could use a JavaScript Media Query to determine the width of the screen as detailed here.
var mq = window.matchMedia( "(min-width: 500px)" );
The matches property returns true or false depending on the query result, e.g.
if (mq.matches) {
// window width is at least 500px
} else {
// window width is less than 500px
}
First Detect the Mobiles/Tablets Touch Event:
function is_touch_device() {
return 'ontouchstart' in window // works on most browsers
|| 'onmsgesturechange' in window; // works on ie10
};
Then Try like this:
function eventFire() {
var _element = $(".popover-controls div");
// True in Touch Enabled Devices
if( is_touch_device() ) {
_element.click(function(e) { .... });
}
else {
// apply Hover Event
_element.hover();
}
}
No need to detect width of devices ;)
There is one more solution with third party and Most popular library is Modernizr
This worked for me. It's a combination of the matchMedia() functionality #Ḟḹáḿíṅḡ Ⱬỏḿƀíé shared as well setTimeout() functionality #Jeff Lemay shared at TeamTreeHouse.com
The primary thing I contributed to was the use of the .unbind() functionality. It took me quite a while to figure out that this was necessary so the .hover() and .click() functions don't cross wires.
//Add/remove classes, in nav to show/hide elements
function navClassHandler(){
if($(this).hasClass('active')){
$('.dropdown').removeClass('active');
}else{
$('.dropdown').removeClass('active');
$(this).addClass('active');
}
}
function handleNav() {
//instantanteous check to see if the document matches the media query.
const mqM = window.matchMedia('(max-width: 1025px)');
const mqD = window.matchMedia('(min-width: 1025px)');
$('.dropdown').unbind(); //necessary to remove previous hover/click event handler
if (mqM.matches) {
console.log("Handling mobile");
$('.dropdown').click(navClassHandler);
} else {
console.log("Handling desktop");
$('.dropdown').hover(navClassHandler);
}
}
// we set an empty variable here that will be used to clearTimeout
let id;
/* this tells the page to wait half a second before making any changes,
we call our handleNav function here but our actual actions/adjustments are in handleNav */
$(window).resize(function() {
clearTimeout(id);
id = setTimeout(handleNav, 500);
});
//As soon as the document loads, run handleNav to set nav behavior
$(document).ready(handleNav);
So, a few users are experiencing their browser window minimizing when they click save on this modal window. For those users, it's consistent, but it's just a small number of users. Most people are using IE9, and everyone that has this problem is using IE9. It happens on the .dialog('close'); call, and it minimizes before it reaches the close function. Does anyone have any ideas?
$("#new-specified").dialog($.extend({}, ns.modalOptions, {
open: function () {
if (ns.disabled) {
$(this).dialog("close");
}
$(this).dialog("option", "title", app.viewModels.MissionViewModel.EditingSpecified() ? "EDIT SPECIFIED TASK" : "NEW SPECIFIED TASK");
$(this).parent().find("button:contains('Cancel')").removeClass().addClass("cancel-button");
$(this).parent().find("button:contains('SAVE')").removeClass().addClass("save-button");
app.viewModels.MissionViewModel.CurrentSpecified().TempDescription(app.functions.htmlUnescape(app.viewModels.MissionViewModel.CurrentSpecified().Description()));
if (app.viewModels.MissionViewModel.SpecifiedTasks().length === 0) {
app.viewModels.MissionViewModel.CurrentSpecified().IsMainEffort(true);
}
},
buttons: {
"Cancel": function() {
$(this).dialog("close");
},
"SAVE": function () {
var newSpecified = app.viewModels.MissionViewModel.CurrentSpecified();
newSpecified.Description(app.functions.htmlEscape(newSpecified.TempDescription()));
newSpecified.Validate();
if (newSpecified.IsInError()) {
return;
}
if (!app.viewModels.MissionViewModel.EditingSpecified()) {
app.viewModels.MissionViewModel.SpecifiedTasks.push(newSpecified);
} else {
app.viewModels.MissionViewModel.OldSpecified().CopyFrom(newSpecified);
newSpecified = app.viewModels.MissionViewModel.OldSpecified();
}
app.viewModels.MissionViewModel.CurrentSpecified(new app.models.SpecifiedTaskViewModel());
var isMainEffort = newSpecified.IsMainEffort();
var index = isMainEffort ? app.viewModels.MissionViewModel.SpecifiedTasks().indexOf(newSpecified) : -1;
app.viewModels.MissionViewModel.VerifyMainEffort(index);
ns.setupSpecifiedModal();
//VV This line below minimizes
$(this).dialog("close");
ns.setupDroppable();
}
},
close: function() {
// We don't reach here before the window minimizes
app.viewModels.MissionViewModel.CurrentSpecified(new app.models.SpecifiedTaskViewModel());
app.viewModels.MissionViewModel.EditingSpecified(false);
app.viewModels.MissionViewModel.VerifyMainEffort(-1);
ns.saveMissionToServer();
}
}));
This question might have the solution: Dynamically loading jQuery mobile causes IE to minimize
Seems like calling blur() forces the IE window to the back of the stack. If you're using jQuery Mobile, here is the related issue: https://github.com/jquery/jquery-mobile/issues/2057
If you're not using jQuery Mobile, look for calls to blur() in your code.
This was also found in jquery-UI 1.10.0: http://bugs.jqueryui.com/ticket/9420.
As first comment suggest, the cause is that blur() is called on document.body.
As a workaround you can override body.blur(), look at How do I disable body.blur() in IE8?
I have two stores with autoload: true being loaded with data. I want to fill my UI after both of these have loaded. I am following the MVC architecture, so in my Controller, I am trying to do something like this:
store1.on('load', me.setUpIfBothStoresReady, me);
store2.on('load', me.setUpIfBothStoresReady, me);
setUpIfBothStoresReady: function() {
if(store1.isSuccessfullyLoaded() && store2.isSuccessfullyLoaded()) {
// do work
}
}
The problem is that at this point, either one or both store could already be loaded. Apart from controlling the load on these stores manually, is there some design pattern I can use to do work only after both are done?
You can use something like whenjs with defered events.
https://github.com/cujojs/when/wiki/Examples
Or write your own:
loadStores: function() {
...
me.loaded = 0;
store1.on('load', me.setUpIfBothStoresReady, me);
store2.on('load', me.setUpIfBothStoresReady, me);
},
...
setUpIfBothStoresReady: function() {
++this.loaded;
if (this.loaded == 2) {
//do work
}
}
if you have a few stores, will be better use array.
Problem solved: I removed the first function as it wasn't needed anyways, and now it all works in all browsers. Thanks for the posts though!
My issue here is that I have a javascript which on one server runs perfectly with no issues what-so-ever in IE. But on another server gives me 2 errors in IE.
It claims that my offset().top is either Null or not an object.
My fade in and out effect doesn't even become active.
Then I have another HUGE issue, which is that in FireFox NON of it all works.
OPS: This is a webpart, so additional javascripts running on the site might could intervene with the javascript I am trying to execute here. But I'm not sure.
I've tested this webpart in IE 8.0.7600.16385, on both servers.
Script:
<script type="text/javascript"
src="/_layouts/Progressive/Javascripts/jquery-1.4.3.js"></script>
<script type="text/javascript">
(function($) {
$.fn.goTo = function() {
// This is where IE on the second server claims the error to be.
$('html, body').animate({scrollTop: $(this).offset().top + 'px'}, 'fast');
return this;
}
})(jQuery);
function showParagraphs(sender) {
var id = sender.getAttribute('href');
if ($('#<%=paragraph.ClientID%>').hasClass("readable")) {
$('#<%=paragraph.ClientID%>').removeClass("readable");
highlightSelected(id);
}
else {
$('#<%=paragraph.ClientID%>').addClass("readable");
rmvClass(id);
}
};
function highlightSelected(id) {
$(id).goTo();
$(id).addClass("reading");
// This part is what isn't activated on the second server.
$('.reading').fadeOut(400).fadeIn(400).fadeOut(400).fadeIn(400);
// .reading only adds a gray background to the DIV.
};
function rmvClass(id) {
$('div').each(function() {
if ($(this).hasClass("reading")) {
$(this).removeClass("reading");
}
});
}
function toTop() {
$('div').each(function() {
$(this).removeClass("reading");
});
$('#<%=paragraph.ClientID%>').addClass("readable");
}
$(document).ready(function() {
$('#<%=q.ClientID%>').find('dd').hide().end().find('dt').click(function() {
$(this).next().slideToggle("fast");
});
$("#<%=q.ClientID%> dt").click(function() {
if ($(this).hasClass("selected")) {
$(this).removeClass("selected");
}
else {
$(this).addClass("selected");
}
});
});
</script>
Any thoughts or suggestions?
When
$(id)
returns an empty jQuery object, then ".offset()" will return null. You're calling that "highlightSelected" code with the "href" value from something, so perhaps what you think to be an "id" value that corresponds to something on the page, well it really doesn't. It's hard to know for sure, however, because you did not post any of the relevant HTML, nor did you even show where "showParagraphs()" is called!