I am making a mobile web application (using JavaScript) for chatting, so think of the user interface like Viber or WhatsApp or any other chat application, but in a browser instead.
You can see alive demo here: https://mandarini.github.io/chatsim/
You can access this from your phone. The problem is clearly illustrated.
You can find the code here: https://github.com/mandarini/chatsim
I have an input form box with position fixed that stays at the bottom of the browser window. The messages are above the text box, and they scroll behind it, like the message boxes do in WhatsApp.
When the virtual keyboard on my phone appears, that is when I am about to type something, the text box is indeed pushed up, and is fixed at the bottom of the viewport screen, right above the keyboard as expected.
However, the chat messages are not pushed up. As a result, the latest messages are hidden behind the keyboard.
Image 1: Keyboard is hidden
Image 2: Keyboard is shown, messages are hidden behind it
Image 3: Expected result, keyboard is shown, messages are pushed up
Note 1: One main problem is that there is no javascript event that catches the expanse/collapse of the virtual keyboard.
Note 2: The onfocus event does not necessarily capture the expanse/collapse, since a virtual keyboard can be hidden, but still the text box may remain focused.
Below you can find a simplified version of my code, which mocks the posting of messages.
I want the newly posted messages to appear above the virtual keyboard on mobile devices.
function addMsg(e) {
e.preventDefault();
var message = document.createElement("div");
var user = document.createElement("p");
var text = document.createElement("p");
user.appendChild(document.createTextNode("User"));
text.appendChild(document.createTextNode("Message message"));
message.appendChild(user);
message.appendChild(text);
message.classList.add("chat-msg");
document.getElementById("chats").appendChild(message);
message.scrollIntoView();
return false;
}
.chat-container {}
.chat-messages {
overflow: scroll;
padding-bottom: 66px;
/* leaves space for input */
}
.chat-form {
width: 100%;
margin: 0;
position: fixed;
bottom: 0px;
background-color: #ffffff;
border-top: 1px solid rgba(0, 0, 0, 0.12);
padding: 7px 8px 7px 8px;
}
input[type=text] {
width: 96%;
padding: 17px 20px;
margin: 0;
background-color: #fafafa;
box-sizing: border-box;
border-radius: 1px;
border: 0px;
box-shadow: 0;
}
.hidden {
display: none;
}
.chat-msg {
padding: 8px;
margin-bottom: 8px;
font-size: 14px;
width: auto;
max-width: 90%;
clear: both;
word-wrap: break-word;
border-radius: 3px;
border-style: solid;
border-width: 1px;
}
.chat-msg p {
margin: 0;
padding: 0;
text-align: left;
}
<div id="chat" class="chat-container">
<div id="chats" class="chat-messages">
</div>
<form onsubmit="addMsg(event)" class="chat-form">
<label>
<input type="text">
</label>
<input class="hidden" type="submit" value="Post" />
</form>
</div>
I believe you can use the 'focusout' event for this.
document.addEventListener('focusout', e => {
window.scrollTo(0, 0);
});
Also sent a PR: https://github.com/mandarini/chatsim/pull/1
Related
I have to code a 3 pages website for my school's first year exam.
The website have to work on any computer and on a mobile device (specifically a Nexus 5).
I have created a button on the second page that give random sentences every time you click on it. It perfectly work on computer but every time I put my website on a mobile device (emulators, etc) the button doesn't work.
i saw a lot of people online having the same problem but non of the solution worked or corresponded to my issue.
Here are my codes for the button;
var news = [
'omg i need help',
'haaaaaaaaa',
'skdkskfsjize',
'I ll fail my exams so bad',
'blablabla',
]
function newNews() {
var randomNumber = Math.floor(Math.random() * (news.length));
document.getElementById('newsDisplay').innerHTML = news[randomNumber]
}
.boite {
overflow: hidden;
position: fixed;
background-position: right;
float: right;
font-size: 14px;
line-height: 13px;
width: 200px;
display: inline-block;
vertical-align: right;
margin-left: -806px;
margin-top: 43px;
background-color: darkolivegreen;
border-bottom-style: groove;
border-width: thick;
}
<button type="button" style="height: auto; width: 200px;" onClick="newNews();" onTouch="newNews();">News</button>
<div id="newsDisplay" class="boite"></div>
Thank you for your time
Replace your margin-left value with a lesser value or with a percentage rather than a pixel in your css to prevent the div from being placed off display in mobile screens.
Also, add a unique id to your button and add event listeners to it in the JavaScript itself rather than writing your scripts inline like this:
/* JavaScript */
var btn = document.getElementById("newsBtn");
var news = ['a','b','c','d','e',];
function newNews (e) {
e.preventDefault();
var randomNumber = Math.floor(Math.random()*(news.length));
document.getElementById('newsDisplay').innerHTML = news[randomNumber];
}
btn.addEventListener("click", newNews);
btn.addEventListener("touchstart", newNews);
<!-- HTML -->
<button id="newsBtn" type="button">News</button>
<div id="newsDisplay" class= "boite"></div>
N.B. The e.preventDefault is for preventing both event listeners from being fired on certain mobile devices that simulates a mouse click when an element is touched or on devices like touch-screen laptops where both events are simultaneously fired.
Check this article on handling events for a more in-depth explanation of how you can handle both events on a single element.
So i simplified your script a little. See the Jsfiddle
What mostly went wrong was the css
margin-left: -806px;
Margin-left ensured that it fell outside the screen. Also tested it with mobile debug, works fine.
Remove the margin-left property - it places the div element off-screen - and you might also want to change the background-color to something more visible!
var news = [
'omg i need help',
'haaaaaaaaa',
'skdkskfsjize',
'I ll fail my exams so bad',
'blablabla',
]
function newNews() {
var randomNumber = Math.floor(Math.random() * (news.length));
document.getElementById('newsDisplay').innerHTML = news[randomNumber]
}
.boite {
overflow: hidden;
position: fixed;
background-position: right;
float: right;
font-size: 14px;
line-height: 13px;
width: 200px;
display: inline-block;
vertical-align: right;
margin-top: 43px;
background-color: darkolivegreen;
border-bottom-style: groove;
border-width: thick;
}
<button type="button" style="height: auto; width: 200px;" onClick="newNews();" onTouch="newNews();">News</button>
<div id="newsDisplay" class="boite"></div>
Margin left seems to be the problem here. Remove that everything will be working fine.
Check this.
var news = [
'omg i need help',
'haaaaaaaaa',
'skdkskfsjize',
'I ll fail my exams so bad',
'blablabla',
]
function newNews() {
var randomNumber = Math.floor(Math.random() * (news.length));
document.getElementById('newsDisplay').innerHTML = news[randomNumber]
}
.boite {
overflow: hidden;
position: fixed;
background-position: right;
float: right;
font-size: 14px;
line-height: 13px;
width: 200px;
display: inline-block;
vertical-align: right;
/*margin-left: -806px;*/
margin-top: 43px;
background-color: darkolivegreen;
border-bottom-style: groove;
border-width: thick;
}
<button type="button" style="height: auto; width: 200px;" onClick="newNews();" onTouch="newNews();">News</button>
<div id="newsDisplay" class="boite"></div>
I have a link at the very top of the page called "Skip Navigation", that appears on the screen every time user presses Tab, and if he presses Enter while "Skip Navigation" is in focus, it takes him to the #main part of the page, so that he skips top navigation and goes directly into the main area. It all works perfect in Chrome, Firefox, Safari. The issue appears in IE (I tested both ie9 and ie11).
Scenario in IE:
Presses Tab - "Skip Navigation" appears on the page - presses Enter -
refreshes the page with #main added into the url - presses Tab - "Skip
Navigation" appears on the page
Does anyone know any solution for IE to force skipping navigation and going to the main part of the page? Any help will be highly appreciated.
#skip a {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
#skip a:focus {
left: auto;
font-size: 20px;
position: static;
width: auto;
height: auto;
}
nav {
background: #847577;
color: white;
padding: 1em;
text-align: center;
}
nav a {
color: white;
}
#main {
background: #E5E6E4;
padding: 1em;
}
#main a {
color: black;
}
<div id="skip">Skip navigation</div>
<nav>
Home
About Us
</nav>
<div id="main">
Main Content On The Page Link
</div>
jsfiddle: https://jsfiddle.net/13p0eo43/
I think you have two options if it doesn't work with the standard way as you describe:
Focus the first focusable element following #main using JavaScript .focus() method. Your difficulty here will be determining which element must be focused, as it might not always be so simple.
Set tabindex=-1 on #main and focus #main using JavaScript .focus() method upon clicking on the link. The next time the user press tab, the next focusable element will take focus, and #main can't be focused again when pressing shift+tab (because of the value -1).
Add tabindex="-1" to the div, no need for javascript.
The following is working for me in IE11.
#skip a {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
#skip a:focus {
left: auto;
font-size: 20px;
position: static;
width: auto;
height: auto;
}
nav {
background: #847577;
color: white;
padding: 1em;
text-align: center;
}
nav a {
color: white;
}
#main {
background: #E5E6E4;
padding: 1em;
}
#main a {
color: black;
}
<div id="skip">Skip navigation</div>
<nav>
Home
About Us
</nav>
<div id="main" tabindex="-1">
Main Content On The Page Link
</div>
I am using the code below to show a message when a mobile device (smartphone or tablet) is in portrait mode. This works fine!
However, I need code that when the user clicks on the X-button, the message does not appear anymore as long as ANY of the pages of the website are being visited in that session.
But if the website is closed; at the next visit the message should appear again when the website is viewed in portrait mode.
How can this be done?
html,
body {
width: 100%;
height: 200%;
}
#warning-message {
display: none;
}
#media only screen and (orientation:portrait) {
#warning-message {
display: block;
}
}
#media only screen and (orientation:landscape) {
#warning-message {
display: none;
}
}
#landscape-button {
background-color: #2A3847;
color: #ffffff;
border-radius: 0px;
border: 1px solid white;
padding: 10px 10px 10px 10px;
float: right;
margin-top: -25px;
margin-right: -15px;
font-size: 1.3em;
}
Please open in "full page" mode and scale your window to a portrait size to see the message appear.<br><br>
<div id="warning-message" style="position:fixed; margin: 0 auto 0 auto; z-index: 99999999; background-color: #2A3847; width: 90vw; min-height: 90vh; text-align:center; padding:25px 15px 35px 15px; right: 0;
left: 0;
margin-right: auto;
margin-left: auto;">
<button type="button" id="landscape-button">X</button>
<p style="font-size: 1.3em; color: #ffffff; positie:absolute; text-align:center;"><span style="margin: 0 0 0 25px; text-align:center; font-size: 2em; letter-spacing: -0.04em;">please rotate your screen</span><br><br>This website is best viewed in landscape mode. So please, rotate your mobile device, and if activated also disable
your screen rotation lock. If you prefer to remain in portrait mode, ignore this message and close it at the "x".</p>
</div>
You'll want to use sessionStorage - https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage
When user clicks "X":
sessionStorage.setItem('closed', 'true');
When re-loading the page:
var data = sessionStorage.getItem('key');
if (data == 'true') {
// do nothing
} else {
// display block
}
Below is what works, taking into account that the session storage only starts after the "X" button is clicked. So even if the page is reloaded before the close button "X" is clicked, the message will still appear when the window is sized to portrait mode or if the mobile device is held in portrait mode. After the "X" button is clicked, the message will no longer appear upon reload of the page within the same session.
See the example here!
$(document).ready(function() {
var data = sessionStorage.getItem('isfirst');
if (data == undefined) {
$("#warning-message").addClass("shown-modal");
} else {
$("#warning-message").hide();
}
});
//close the pop
$("#landscape-button").on('click', function() {
sessionStorage.setItem('isfirst', 'true');
$("#warning-message").hide();
});
I have a little issue with my context menu, the CSS doesn't apply and the event on click doesn't work too. If i inspect the element with F12 (on IE 11), I can see the CSS is on the page (in the header) and I can see that all line of the context menu have the event on click but it doesn't work when I click.
CSS :
.ctxmenu
{
position: absolute;
height: auto;
padding: 0px;
margin: 0;
margin-left: 0.5em;
margin-top: 0.5em;
border: 1px solid black;
background: #F8F8F8;
z-index: 11;
overflow: visible;
}
.ctxline
{
display: block;
margin: 0px;
padding: 2px 2px 2px 8px;
border: 1px solid #F8F8F8;
overflow: visible;
}
.ctxline:hover
{
border: 1px solid #BBB;
background-color: #F0F0F0;
background-repeat: repeat-x;
}
for the constitution of the contextMenu :
for (i = 0; i < listCorrection.length; ++i) {
var p = document.createElement('p');
d.appendChild(p);
p.setAttribute('class', 'ctxline');
p.setAttribute('onclick', 'alert("do something");');
p.innerText = listCorrection[i];
}
when I inspect the element of this context Menu i can see :
<p onclick="alert("do something");" class="ctxline">set</p>
and the div containing the context Menu :
<div id="ctxmenu1" style"CURSOR: pointer" class="ctxmenu">(the p on context menu are here)</div>
does anybody have an idea why ? i try to moove it Inside the header with a but it is still not working.
Well after several hours spend on this issue i might have find a fix, if someday someone end up on this page try this :
replace every line that are like this :
p.setAttribute('class', 'ctxline');
by something like this :
p.className = 'ctxline';
I know it's the same thing, but well IE so sometimes you have to think outside the box (this fix work for IE11, IE9, I did not test with other Navigator).
I have the basic idea of my JavaScript operational.
The point of my JavaScript is to make an image of id 'player' move to the position that I click with the mouse, only when I click on the div with the id of 'stage' with the animation lasting 3 seconds.
At the same time, when the animation is running the head should change to 'player is moving' as opposed to when it is still and displaying 'player is still'.
Right now, in Chrome (maybe its a bug with Chrome) the basic functionality of the JS works. However, it seems to overshoot the position of where I click the mouse on the first round and then barely move when I click again in the 'stage' div.
If anyone sees where I might be running into a problem please let me know!
Here's my EDITED JQuery:
$(document).ready(function(){
$('#stage').click(function(e){
$('#header h1').html('Player is moving!');
$('#player').animate({
top: e.pageY + 'px',
left: e.pageX + 'px'
}, 3000, function(){
$('#header h1').html('Player is standing still...');
});
});
});
I have fixed my CSS issue, so don't worry about that but the code is located below for the CSS in case anyone thinks the issue may lie within.
Thanks!
EDIT:
Here's the CSS. The issue has been solved but it has been provided for convenience if you think the issue of the image overshooting the image may lie within for any reason:
#header {
width: 600px;
margin: 20px auto 10px;
padding: 5px;
background-color: whiteSmoke;
border: 1px solid #aaa;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
box-shadow: 0 0 5px #ccc;
}
#header h1 {
text-align: center;
margin: 0;
}
#stage {
overflow: hidden;
width: 600px;
height: 400px;
margin: 0 auto;
padding: 5px;
background-color: whiteSmoke;
border: 1px solid #aaa;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
box-shadow: 0 0 5px #ccc;
position: relative;
}
#player {
position: absolute;
width: 36px;
}
Poor man's example : jsfiddle but it works in FF and Chrome.
Also, I'm curious what styles you lose, simple color style is always applied.
So more information is needed, can you share the complete css?
Update: I'm still not seeing an issue in chrome (with the fiddle example)
Change #stage to something like
#stage {width:600px;height:600px;background-color:#333;position:fixed;top:20;left:0;}
Your player vs page is lying about it's position or where you can click. I wanted the stage to be a fixed item on the page, non-moving. I don't see any other reason (in your CSS or jQuery) why it'd overshoot.