window.print() , google maps blank space between screenshot - javascript

I'm currently working on an aspx Page , the main page functionality is to display a google maps path composed by several markers (huge amount) , i'd need to add a print option (A3/A4 Format) ,and i've been using the window.print() function to achieve this , as i've been stuck having issues trying with other methods (like google maps api) , here's my current issue : using window.print() i'm able to get the printing of the map with the right formats , however there's a blank space being showed on the printout , here's an example A4(1050,625):
screenshot
The code:
function print(width,height){
var cDiv = document.createElement('div');
cDiv.setAttribute('id','mainContainer');
cDiv.innerHTML='<div id="mapContainer"></div>';
var jqMapContainer = $("#map");
mapContainer = jqMapContainer[0];
var origDisplay = [],
origMapParent = mapContainer.parentNode;
body = window.document.body;
childNodes = body.childNodes;
// hide all body content
$.each(childNodes, function (i, node) {
if (node.nodeType === 1) {
origDisplay[i] = node.style.display;
node.style.display = 'none';
}
});
body.appendChild(cDiv);
var rc = document.getElementById('mapContainer');
rc.appendChild(mapContainer);
$("#mainContainer").width(width);
$("#mainContainer").height(height);
$(mapContainer).width(width);
$(mapContainer).height(height);
setTimeout(function () {
window.print();
}, 4000);
var _self = this;
// allow the browser to prepare before reverting
setTimeout(function () {
// put the chart back in
origMapParent.appendChild(mapContainer);
$("#mainContainer").remove();
// restore all body content
$.each(childNodes, function (i, node) {
if (node.nodeType === 1) {
node.style.display = origDisplay[i];
}
});
google.maps.event.trigger(map, 'resize');
}, 4000);
}
the div element that contains the map:
<div class="CenterRightColMap">
<div class="contentCC">
<div id="map" class="mapFullPage"></div>
</div>
</div>
Style:
div.mapFullPage
{
width:100%;
height:98%;
}
div.contentCC {
position:relative;
padding: 5px;
margin: 5px 5px 0px 5px;
border: 1px solid #000000;
/*background: #FFFFFF;
color: #666666;
font-family: Tahoma,Verdana,Helvetica,Helvetica-Narrow,sans-serif;*/
text-align:center;
height:100%
}
div.CenterRightColMap
{
position:absolute;
float: auto;
left:430px;
right:20px;
height:85%;
min-height:85%;
FONT-SIZE: 8pt;
background-color: #CECECE;
FONT-FAMILY: Verdana;
padding: 5px
}

Found the solution here : https://bugs.chromium.org/p/chromium/issues/detail?id=426294
Managed to fix it using adding the following style to the page
<style>.gm-style div > img {position: absolute;}</style>
Appears to be a bug from gm

Related

How to link HTML Element with Python function in Jupyter notebook?

I've written JavaScript code that shows a custom right click menu.
I'd like to know how to trigger Python functions upon my menu items being clicked. These menu items are the divs nested under the div with the class of menu, which consequently is the only element in the body section of my HTML.
The environment I'm using is Jupyter Notebook.
notebook.
import jinja2
from bokeh.embed import components
template = jinja2.Template("""
<!doctype html>
<html>
<head>
<script>
src="http://cdn.pydata.org/bokeh/dev/bokeh-0.13.0.min.js"
var menuDisplayed = false;
var menuBox = null;
window.addEventListener("contextmenu", function() {
var left = arguments[0].clientX;
var top = arguments[0].clientY;
menuBox = window.document.querySelector(".menu");
menuBox.style.left = left + "px";
menuBox.style.top = top + "px";
menuBox.style.display = "block";
arguments[0].preventDefault();
menuDisplayed = true;
}, false);
window.addEventListener("click", function() {
if(menuDisplayed == true){
menuBox.style.display = "none";
}
}, true);
</script>
<style>
.menu
{
width: 150px;
box-shadow: 3px 3px 5px #888888;
border-style: solid;
border-width: 1px;
border-color: grey;
border-radius: 2px;
padding-left: 5px;
padding-right: 5px;
padding-top: 3px;
padding-bottom: 3px;
position: fixed;
display: none;
}
.menu-item
{
height: 20px;
}
.menu-item:hover
{
background-color: #6CB5FF;
cursor: pointer;
}
</style>
</head>
<body>
<div class="menu">
<div class="menu-item">Add Node</div>
<div class="menu-item">Delete Node</div>
<div class="menu-item">Update Node</div>
</div>
</body>
</html>
""")
I think you will get clear understanding and clarity on this with below example easily:
// %%javascript
window.executePython = function(python) {
return new Promise((resolve, reject) => {
var callbacks = {
iopub: {
output: (data) => resolve(data.content.text.trim())
}
};
Jupyter.notebook.kernel.execute(`print(${python})`, callbacks);
});
}
// Use it in any Jupyter JS/HTML cell like this
%%javascript
window.executePython("1 + 1")
.then(result => console.log(result)); // Logs 2
// You can access any defined object/method in the notebook
// I suggest writing a function that returns your data as JSON and just calling the function.

CSS style shows after refresh and then goes invisible with Knockout

So I have a new notification style ring and green circle with unread notifications in it this circle only is visible when you have new notifications.
when page is refreshed even if you dont have a notification the circle is visible for a second and then goes invisible
If there is a new notification still when refreshed circle shows up empty or with zero and then goes invisible and then with correct number
HTML:
<div class="bell">
<div class="unseen-notification-show" data-bind="visible: UnSeenMessagesCount() > 0, text: UnSeenMessagesCount()" style="display:none"></div>
</div>
CSS:
.unseen-notification-show {
content: '';
display: block !important;
position: absolute;
top: -10px;
right: -8px;
width: 17px;
height: 17px;
border: 1px solid #ffffff;
background-color: #8cdb16;
border-radius: 8px;
cursor: pointer;
z-index: 3;
color: white;
text-align: center;
line-height: 15px;
font-size: 11px;
font-family: 'Times New Roman', Times, serif;
}
self.searchModel = new AuthorizedSearchViewModel();
self.Header = ko.observable(new HeaderModel());
self.UnSeenMessagesCount = ko.observable(0);
self.Messages = ko.observableArray();
self.CanShowRemindProfile = ko.observable(false);
self.Remind = ko.observable(new RemindModel());
self.LoadUserInformation = function () {
$.post('/User/GetUserInfoForDashboardHeader',
function (response) {
InitTawkChat(response);
self.Header(new HeaderModel(response));
if ($('#accountId').length > 0) {
$('#accountId').html(response.accountId);
}
}, "json").done(function () { console.warn("loaderOff"); });
};
self.GetRemindProfile = function () {
self.CanShowRemindProfile(false);
$.post('/User/GetRemindProfile', function (result) {
if (result) {
self.CanShowRemindProfile(true);
self.Remind(new RemindModel(result));
}
});
};
self.GetMessages = function () {
$.post('/Messages/GetAll', {
page: 1,
pageSize: 4
}, function (result) {
var notifications = [];
_.map(result.Notifications, function (item) {
notifications.push(new MessageModel(item));
});
self.Messages(notifications);
self.UnSeenMessagesCount(result.UnseenNotifications);
});
};
Remove !important from display property in your css and let knockout inline handle display.
function viewModel(){
var self = this;
self.UnSeenMessagesCount = ko.observable();
self.initData = function(){
//dummy setTimeout for your ajax get.
setTimeout(function(){
self.UnSeenMessagesCount(4);
},1000);
}
}
var vm = new viewModel();
vm.initData();
ko.applyBindings(vm);
.unseen-notification-show {
content: '';
display: block;
position: absolute;
width: 17px;
height: 17px;
border: 1px solid #ffffff;
background-color: #8cdb16;
border-radius: 8px;
cursor: pointer;
z-index: 3;
color: white;
text-align: center;
line-height: 15px;
font-size: 11px;
font-family: 'Times New Roman', Times, serif;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div class="bell">
<div class="unseen-notification-show" data-bind="visible: UnSeenMessagesCount() > 0, text: UnSeenMessagesCount()" style="display:none"></div>
</div>
Sounds like some loading issues. Try moving your css from being loaded in the top of the HTML, to be loaded in the bottom/footer.
What you want to do, is to hide the circle until the result is loaded (either 0 or 1,2,3,4.. and so on. Depending on the number of notifications).
In your div you got this line style="display:none"> which hides the circle. Thats good!
Now you should make sure that the style for .unseen-notification-show which contains display: block !important; that shows the circle - Should not be run before the calculation of the number to show is done.
One way could be to place the file that loads your css to the bottom of the HTML (like moving your <link rel="stylesheet" href="test.css" />). Or another way is to only use css for the hiding and then use javascript/jQuery for showing the cirle.
If this didn't help - then please provide the code you use to generate the number.
I think the issue is due to
self.UnSeenMessagesCount = ko.observable(0);
so when your modal is getting created it is initialized with value 0. So when you refresh the page initially it is 0 but when self.getMessage is called it updates your value.

Javascript: removeChild at certain screen size

I'm trying for hours now to add a wrapper around two divs (aside and .related) at a certain screensize (>60em and <90em). I'm doing this with matchMedia and an eventListener. The wrapper seems to be added at the right spot, but the problem is that it's still there even when the condition of the size is not met.
Here is a jsfiddle: http://jsfiddle.net/Vanilla__/4q26ngmg/1/
Simplified HTML:
<body>
<header>Header</header>
<main>Main</main>
<aside>Aside</aside>
<div class="related">Related</div>
<footer>Footer</footer>
</body>
Javascript:
if(window.matchMedia("screen and (min-width: 60em) and (max-width: 90em)").matches) {
window.addEventListener("resize", function addWrapper(q) {
//Create div with id wrapper
var div = document.createElement('div');
div.id = "wrapper";
// Select aside
var selectDiv = document.querySelector("aside");
//clone
div.appendChild(selectDiv.cloneNode(true));
//Place the new wrapper at the right place in the HTML
selectDiv.parentNode.replaceChild(div, selectDiv);
//Add related to the wrapper so they're both in the wrapper
document.querySelector('#wrapper').appendChild(
document.querySelector('.related') );
});
}
I wanted to add an 'else' to remove the child (with removeChild) or delete the eventListener (with removeEventListener) when there's another screen size, but all I get is errors about that the function is not definied or other errors whatever I try.
else {
window.removeEventListener("resize", addWrapper(q));
}
Does anyone know how the wrapper can be removed when the screensize is not >60em and <90em? I'm a Javascript rookie (as might be clear ;) ). Any help is appreciated.
You could do something like this:
var addWrapper = function () {
//Don't add wrapper if already added
var wrapper = document.getElementById("wrapper");
if (wrapper !== null) return;
//Create div with id wrapper
var div = document.createElement('div');
div.id = "wrapper";
// Select aside
var selectDiv = document.querySelector("aside");
//clone
div.appendChild(selectDiv.cloneNode(true));
//Place the new wrapper at the right place in the HTML
selectDiv.parentNode.replaceChild(div, selectDiv);
//Add related to the wrapper so they're both in the wrapper
document.querySelector('#wrapper').appendChild(
document.querySelector('.related'));
};
var removeWrapper = function () {
//Don't remove if there is no wrapper
var wrapper = document.getElementById("wrapper");
if (wrapper === null) return;
//Replace wrapper with its content
wrapper.outerHTML = wrapper.innerHTML;
}
var wrapperFixer = function () {
if (window.matchMedia("screen and (min-width: 60em) and (max-width: 90em)").matches) {
addWrapper();
} else {
removeWrapper();
}
}
window.onload = function () {
window.addEventListener("resize", wrapperFixer);
//Check and add if wrapper should be added on load
wrapperFixer();
}
body {
display: flex;
height: 40em;
flex-wrap: wrap;
font-family: Helvetica, Arial, sans-serif;
color: white;
text-align: center;
}
header {
background-color: purple;
width: 30%
}
main {
background-color: pink;
width: 40%
}
aside {
background-color: deepPink;
width: 15%
}
.related {
background-color: red;
width: 15%
}
footer {
background-color: slateBlue;
width: 100%;
height: 5em;
}
#wrapper {
border: 4px solid white;
}
<body>
<header>Header</header>
<main>Main</main>
<aside>Aside</aside>
<div class="related">Related</div>
<footer>Footer</footer>
</body>

JavaScript styling of DOM shadow host

I'd written the below code, based on my understanding of this:
The host is not styled!!
var fonixDiv = Object.create(HTMLElement.prototype);
// Set up the element.
fonixDiv.createdCallback = function() {
// Create a Shadow Root
var shadow = this.createShadowRoot();
shadow.innerHTML = '<style>'+
':host { width:200px; height:200px; background: #b0c4de; }'+ // Not working
'p{color: red;}'+ // Working
'</style>'+
'<p>hi</p><button id="d">click</button>';
shadow.children.d.addEventListener('click', function(e) {
this.textContent = "you clicked me :(";
shadow.children[1].textContent="Shadow DOM content changed";
host.style.background = "green"; // working
alert("All: button, text and host should be change");
});
};
// Register the new element.
var Xfonix =document.registerElement('fonix-div', {
prototype: fonixDiv
});
UPDATE
in the html file, I call it as:
<fonix-div></fonix-div>
and as:
<div id='host'></div>
<script>
var host = document.querySelector('#host');
var el = new Xfonix();
host.appendChild(el);
<script>
any help how to style the host element!
fiddle is here
nothing is working for host styling, neither width, nor height nor background :(
I was able to solve the issue using css file:
the .html file is:
<fonix-div></fonix-div>
<div id="host1"></div>
the .js file is:
// Create a new object based of the HTMLElement prototype
var fonixDiv = Object.create(HTMLElement.prototype);
// Set up the element.
fonixDiv.createdCallback = function() {
// Create a Shadow Root
var shadow = this.createShadowRoot();
shadow.innerHTML = '<button id="d">click</button>';
shadow.addEventListener('click', function(e) {
console.log('1: '+this.host.dataset.disabled);
this.host.dataset.disabled='true'; // set Attribute to the custom element
});
shadow.children.d.addEventListener('click', function(e) {
this.textContent = "you clicked me :(";
shadow.children[1].textContent="Shadow DOM content changed";
this.disabled=true;
alert("All: button, text and host should be change");
});
};
// Register the new element.
var Xfonix =document.registerElement('fonix-div', {prototype: fonixDiv});
var thehost = document.querySelector('#host1');
thehost.appendChild(new Xfonix());
the .css file is:
body {background: #F7F7F7;}
fonix-div {
display: inline-block;
width: 200px;
height: 200px;
float: left;
margin: 0.5em;
border-radius: 3px;
background: #FFF;
box-shadow: 0 1px 3px rgba(0,0,0,0.25);
font-family: Helvetica, arial, sans-serif;
-webkit-font-smoothing: antialiased;
}
fonix-div:hover, fonix-div[data-disabled='true']:hover {background: red;}
fonix-div:Active {background: green;}
fonix-div[data-disabled='true'] {background: green;}
fonix-div::shadow p{color: blue;}
the output can be seen here:

Make contents of div scroll down with overflow

I have created a small chat system for a project I am making. The chat is functioning well. However, I cannot figure out how to make it so the div stays at the bottom of the chat, rather than having to scroll down to read the last thing someone said.
I am referring to another similar question posted on here for guidance. How to keep a div scrolled to the bottom as HTML content is appended to it via jquery, but hide the scroll bar?
But it still will not work for me. The chat is then stored in a chat.txt file. Each line is surrounded in tags. The following is the code I am using.
js in header:
$container = $('#chat-area');
$container[0].scrollTop = $container[0].scrollHeight;
$('#sendie').keypress(function (e) {
if (e.which == 13) {
$container = $('#chat-area');
$container.append('<p>' + e.target.value + '</p>');
$container.animate({ scrollTop: $container[0].scrollHeight }, "slow");
}
});
chat.php:
<script type="text/javascript">
// strip tags
name = name.replace(/(<([^>]+)>)/ig,"");
// display name on page
$("#name-area").html("You are: <span>" + name + "</span>");
// kick off chat
var chat = new Chat();
$(function() {
chat.getState();
// watch textarea for key presses
$("#sendie").keydown(function(event) {
var key = event.which;
//all keys including return.
if (key >= 33) {
var maxLength = $(this).attr("maxlength");
var length = this.value.length;
// don't allow new content if length is maxed out
if (length >= maxLength) {
event.preventDefault();
}
}
});
// watch textarea for release of key press
$('#sendie').keyup(function(e) {
if (e.keyCode == 13) {
var text = $(this).val();
var maxLength = $(this).attr("maxlength");
var length = text.length;
// send
if (length <= maxLength + 1) {
chat.send(text, name);
$(this).val("");
} else {
$(this).val(text.substring(0, maxLength));
}
}
});
});
</script>
<p id="name-area"></p>
<div id="chatWrap"><div id="chat-area"></div></div>
<form id="send-message-area">
<p>Your message: </p>
<textarea id="sendie" maxlength = '100' ></textarea>
</form>
</div>
css:
#pageWrap
{
position: fixed;
display: block;
right: 0;
bottom: 0;
background: #8B1918;
box-shadow: 0px 0px 12px #333;
transition: height .5s;
}
#pageWrap p
{
color: white;
font-family: arial;
margin-left: 5px;
margin-bottom: 4px;
}
#chatWrap
{
width: 200px;
height: 200px;
overflow: scroll;
overflow-x:hidden;
box-shadow: 1px 1px 10px #333 inset;
color: white;
font-family: arial;
font-size: 14px;
}
#chat-area
{
padding-left: 11px;
}
#sendie
{
resize: none;
display: block;
width: 92%;
margin-left: auto;
margin-right: auto;
margin-bottom: 6px;
}
I got it (partially) working for you. Here are the issues I discovered:
Try not to name variables starting with $ - it creates unnecessary confusion.
You didn't declare $container as var, so you're using a variable before declaring it.
jQuery supports 99% of everything you can do with plain Javascript, but makes it better. Wherever possible, I changed your code to use jQuery instead.
I'm not sure about e.target.value, but $('#sendie').val() works just as well.
You definitely needed to wrap this in the body onload function.
You want to add e.preventDefault(); in the event handler so that it doesn't put a return character in the box.
You didn't clear the input textarea (with jQuery it's just $('#sendie').val('');).
The font color of the chat message area was white (at least on JSFiddle it was). Messages were invisible due to this.
Here's a fiddle demonstrating everything working (as far as I know) - http://jsfiddle.net/U9XAv/
And here's the updated Javascript:
$(function()
{
var container = $('#chat-area');
container.css('scrollTop', container.css('scrollHeight'));
$('#sendie').keydown(function (e)
{
if (e.which == 13)
{
container.append('<p>' + $(this).val() + '</p>')
.animate({ scrollTop: container[0].scrollHeight) }, "slow");
$(this).val('');
e.preventDefault();
}
});
});
And the CSS I changed:
#chat-area
{
padding-left: 11px;
color: black;
}

Categories

Resources