I have used the '#media only screen' in my CSS to determine how and what information should be shown depending on the users screen size. I have a class called panelContainer which is set to display when the screen is greater than 767px, and a class called mobileContainer which displays when the screen is less than that.
I have a couple of custom controls, one that contains the standard form layout and another that contains the mobile device form layout. Originally I placed a div around each with the appropriate styleClass. The problem with it this way was that although only one form is visible, they were both loaded so this caused save issues.
<xp:div id="panelContainer" styleClass="panelContainer">
<xc:content_sCompany></xc:content_sCompany>
</xp:div>
<xp:div id="mobileContainer" styleClass="mobileContainer">
<xc:content_iCompany></xc:content_iCompany>
</xp:div>
I have since added a div to my Xpage with the styleClass of panelContainer, I then added onLoad and onResize events which return the style.display of the div, these should then write the result to a viewScope. But I found it would only write onLoad and although the function was being called onResize it wouldn't change the viewScope variable.
<xp:scriptBlock id="scriptBlock1" type="text/javascript">
<xp:this.value>
<![CDATA[var init = function() {
obj=document.getElementById('formType');
if(getStyleDisplay(obj)=="none"){
formType='#{javascript:viewScope.put("formFormat","mobile");}';
}else{
formType='#{javascript:viewScope.put("formFormat","standard")}';
}
}
dojo.addOnLoad(init);
dojo.connect(window,"onresize",init);
function getStyleDisplay(obj) {
if(obj.currentStyle) { // IE – Opera
return obj.currentStyle.display;
} else { // firefox
return getComputedStyle(obj,'').getPropertyValue('display');
}
}]]>
</xp:this.value>
</xp:scriptBlock>
<div id="formType" class="panelContainer"></div>
.....this viewScope variable is then used in the following way:
<xc:content_Company xp:key="ContentControl">
<xp:this.facets>
<xc:content_sCompany id="content_sCompany"
xp:key="standard">
</xc:content_sCompany>
<xc:content_iCompany id="content_iCompany"
xp:key="mobile">
</xc:content_iCompany>
</xp:this.facets>
</xc:content_Company>
.....extract from content_Company......
<xp:callback facetName="#{viewScope.formFormat}" id="cbkCompanyFormContent">
</xp:callback>
I feel this is the better way to achieve the result I need, as when I have tried it manually it does only load one of the forms and they work as expected.
I cannot see why the viewScope is not being set properly, it is always being set to 'standard', even if I shrink my page before loading the page. I did try writing the value to a Hidden Input, which worked but whenever I tried to access the value using getComponent("hiddenInput1").getValue() it would return null, even though I could see that value had been set when viewing in firebug.
Ok can you check (or tell me if you already have) through some console.log("") 's that the onResize is being called and the correct display is being pulled down etc.
next it may be firing the onResize but are you then partail refreshing the area which is using the viewScope?
Code example of this: (replace controlID with yours)
XSP.partialRefreshGet("controlID", {
onError: function() { console.log('Error'); }
});
I'm a little confused about what the purpose of using onResize is for ? if is to decide what to show whether on mobile or normal screen there are much more efficient ways of doing this.
Using the new redirect control in the latest release of the ExtLib on openNTF. It does exactly what the name suggests and redirects based on certain expressions. leaving you to drop it on a page and say if mobile (or whatever) redirect to this page.
Having a dummy default load page that checks the useragent string to see which page to load (having a separate mobile / fullscreen pages). This is what the teamroom template application that comes with the ExtLib does with its main.xsp and then this is set as the default launch option.
Or if you are trying to do something with whether the phone / tablet is on landscape or portrait you should be using the onOrientationChange event not onResize. check out this example (not the code in the question is what I'm pointing you too, he has a problem getting that to work in a webview):
how to handle javascript onorientationchange event inside uiwebview
Related
How do I determine the state of a textarea element (:focus, :hover, etc.) in Chrome?
For context, I'm trying to create a web application. After submitting the form on a previous page, the textarea of the new page automatically has the cursor, which I do not want to happen. I've tried to use the jQuery code below, which works in Firefox but not in Chrome:
element = $("#elementID");
if (element.is(":focus")) {
element.blur();
}
In Chrome, the code does not execute the element.blur() in the if statement (meaning the if statement fails). I've checked with a debugger and the element is successfully returned by the id in Chrome. So I think the problem is the state check statement.
I assume the problem is the element state and I want to investigate the element state at that time, preferably using Chrome developer tools. Unfortunately, I can't figure out how to check the current state. I can only figure out how to check if the state is equal to a specific state.
I've searched around but I am only finding answers like set :hover state which discuss how to set a specific state using Chrome dev tools and not how to determine the current state when it could be any state.
I realize that I could check for each possible state at that point in the JavaScript, but it seems like I am missing the correct way to check the state.
Here is a JSFiddle of my specific case. However, I'd be interested to also hear the answer to the general question about determining the current state of a textarea.
Thanks for the help!
It's most likely an order of operations issue - the logic is executed before the input's focus can be detected.
I've reproduced the issue here, and fixed it by putting the code into the window .load() event.
var $el = $('textarea');
// will not execute
if ($el.is(':focus')) {
$el.blur();
console.log('outside of window load');
}
// will execute
$(window).load(function() {
if ($el.is(':focus')) {
$el.blur();
console.log('inside window load');
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea autofocus></textarea>
Running into an interesting browser problem -- I've implemented jQuery to toggle a page's stylesheet link href, on click of a button, between a normal view css file and a print-friendly css file. It works, except that when the viewer goes to the print-friendly version, I call window.print() after the new link href has been applied. The print preview automatically comes up, and in the preview, certain elements that should have display:none in the print-version are visible. If you click "print", then the print comes out screwed up, just like the preview. If you cancel the print, then the page on screen is still in print-friendly mode, but everything is fine and nothing is visible that shouldn't be. And if you then right-click and select "Print..." the preview displays as it should, and everything prints as it should.
This has to be a browser thing, because it's only happening in Chrome, not in FF.
This is the function that gets called whenever the button is clicked:
$('#printOnlyBtn').click(function(){
if ($('#mainStylesheetLink').attr('href') == 'normal.css' {
//switch to print-friendly css file and print
doPrint();
}
else {
//switch back to normal css file
$('#mainStylesheetLink').attr('href', 'normal.css');
}
});
function doPrint(){
$('#mainStylesheetLink').attr('href', 'printFriendly.css');
window.print();
}
One solution is to take out the call to window.print(); just put the page in print-friendly mode with one button, and then have another button the user must click to actually print the page. But I'd prefer to keep it a one-click process if possible.
I'd recommend abandoning your approach of linking to a css file. Instead, try using a #media print { ... } declaration in your css. Include your print-specific styling within this block. There's great documentation at https://developer.mozilla.org/en-US/docs/Web/CSS/#media.
I solved the problem just using setTimeout(). I figured there's a race condition or something like that, so I just delayed the call to window.print() by 100 ms:
function doPrint(){
$('##mainStylesheetLink').attr('href', '#printFriendly.css');
setTimeout(window.print, 100);
}
I actually tried that before, but I coded it as below, forgetting that the code to be executed after delay needs to be passed into setTimeout() as a callback function without the parens, else it gets called immediately:
setTimeout(window.print(), 100);
The setup I have makes an ajax request to a php script to grab some images from the server and display them. During the ajax request, I enable some additional controls. I have two modes for the images, one that brings up a larger version of the image, and one that lets me sort them.
I implemented a checkbox so that I can swap between the two modes. Whenever I click search and invoke the ajax request, the images correspond to the mode that the checkbox had when they were created.
What I want to do is make it so clicking the checkbox allows me to swap the mode without having to search again.
$.ajax({
url: './search.php',
type: 'POST',
success: function(data) {
$("#images").html(data);
enableControls();
},
This is the snippet of the ajax request where I receive the images, add them to my page, and enable the controls.
$('#sortable').change(function() {
enableControls();
});
This is the snippet where I allow my checkbox to change the state of the controls.
function enableControls() {
$('.img-responsive').off();
if($('#sortable').is(":checked")) {
$('.img-responsive').on('dblclick', sortableDoubleClick);
}
else {
$('.img-responsive').on('dblclick', imgDoubleClick);
}
}
This is a snippet where I enable the double click behaviour. Double clicking while it's in sort mode will make that image go to the front (top left) of the rows/columns of images. Double clicking while it's in the non-sort mode will bring up a larger version of the image.
The img-responsive class is a class all the images returned from the search have, and is how I reference them as a group.
Unfortunately, the line
$('.img-responsive').off();
does not work the way I want it to. I want it to completely disable existing controls so I can set whatever new ones I want. It does not do that. What happens right now is that I get both double click controls available.
So let's say I search in non-sort mode and then click my checkbox to put it in sort mode. When I double click on an image, it opens up the larger version of it AND moves it to the top left.
How can I fix this? I assume the way I am invoking .off() is incorrect, but as far as I understand, .off() should remove all the event handlers for the selector, so why is it the case that I still retain the original event handler?
I ended up solving my problem. In the portion of the code:
$('.img-responsive').on('dblclick', imgDoubleClick);
There was some additional code for touch controls:
$('.img-responsive').each(doubletapCover);
For some reason, even though that code path never occurred, it seemed to invoke that code. I made a change so it's not ever called and it fixes my problem.
Thanks to everyone who tried to help.
I am interested in opening a webPanel on the right side of the Firefox window. Based on an MDN article, I determined that this could be done by setting the browser element's direction style. However, I wish to clear out this setting after the webPanel is closed. Is there a way I can detect this? Thus far, the only way I can think of is to poll sidebarWindow.location.href (to detect if the sidebar is changed) and sidebarHidden (to detect if the sidebar is closed).
var browser = document.getElementById('browser');
browser.style.direction = "rtl";
var sidebarWindow = document.getElementById("sidebar").contentWindow;
var sidebarBox = document.getElementById('sidebar-box');
var sidebarHidden = sidebarBox.collapsed || sidebarBox.hidden;
sidebarWindow.addEventListener("unload", function (event) {
alert("1"); //This code fires when the web panel is opened
//but not when it is closed.
});
sidebarBox.addEventListener("unload", function (event) {
alert("2"); //This code does not fire.
});
sidebarWindow.addEventListener("close", function (event) {
alert("3"); //This code does not fire.
});
sidebarBox.addEventListener("close", function (event) {
alert("4"); //This code does not fire.
});
openWebPanel('Test', 'http://www.google.com');
IIRC there are essentially three ways a sidebar can be "closed":
The user closes it using the GUI (X-box) or keyboard shortcut. In this case, the web panel will not necessarily get unloaded, so there is no unload event.
Another document is loaded into the web panel. In this case you might get an unload.
The user opens another panel. There is not necessarily an unload.
Should you go forward with your implementation, you need to make sure your code handles all three correctly.
and 3. should be observable by the <broadcaster id="viewWebPanelsSidebar"> changing the checked attribute (see the implementation of toggleSidebar()), so you could have another element observing and acting on onbroadcast.
should listen for unload and act accordingly.
To get proper unload events, I think the following should do the trick:
sidebar.contentDocument.getElementById("web-panels-browser")).
addEventListener("unload", ...);
But my memory there is a bit wonky, so you might need to fiddle with that a bit. (The sizebar has a <xul:browser id="web-panels-browser"> which displays the actual content...)
After having said all that: I think it is a bad idea to mess with the sidebar like this.
The MDN wiki(!) has bad advice in this case.
The sidebar was not designed to be messed with like this.
There are other add-ons "competing" with yours when it comes to messing with the sidebar.
The sidebar code is, for the most part, pretty archaic and under-maintained. Getting things like your requirement to work correctly is pretty hard. There still might be other code (in add-ons) that could dismiss the sidebar that you and I didn't think of.
The sidebar might not be the best place to display your content in the first place (what that content would be you didn't say). If it's something like context-help, dictionary/definition lookup results, login forms, then it won't be a good fit.
Some users might not like that their always-on bookmarks/history sidebar gets replaced by yours. You could handle this by re-opening the previous one, but that will only complicate matters further.
You might be better off using some other way to display information - e.g. a new tab, a panel, a new sidebar like the social sidebar... E.g the social sidebar is not only on the right, it actually is a standalone sidebar not part of the "main" sidebar.
I currently have a page that is being resized through the use of javascript whenever the end-user resizes the window, so that scrolling is reduced or eliminated when not necessary. I have a loader.js jquery file which picks out .html documents to throw in to the content section of the page when the user selects an option from the left menu:
$("#response").load("home.html");
$("#home").click(function(){
// load home page on click
$("#response").load("home.html");
setTimeout("resizefunc()",500);
});
$("#about").click(function(){
// load about page on click
$("#response").load("about.html");
setTimeout("resizefunc()",500);
});
//etc
While these timeout functions work most of the time, they have the potential to fail if the page loads abnormally slow for any reason. I am using document.ElementId.scrollHeight to determine the height of each new page, but it seems to only detect the height after the changes have been correctly applied. If the javascript loads before the page content then the resize fails.
It seems that if I were using complete html documents for each page then the problem would be irrelevant. I could put an onLoad event in to the body of each one and have it resize there... But since the tag is only loaded once I'm somewhat at a loss. My current implementation "works", but I feel that there should be something more efficient.
Don't use onLoad, instead wrap your code in
$(window).load(function() {
// your code here
});
Also, instead of load() with just the filename as a parameter, use:
$('#response').load('file.html', function() {
resizefunc();
});
Along with "load" you could also use "resize" as one of the events. This would allow dynamic resizing.
$(window).resize(function() {
resizefunc()
});
function resizefunc()
{
// code to resize.
}
See: http://api.jquery.com/resize/