Greasemonkey script seems to ignore setInterval? - javascript

I'm trying to make a toy script in GreaseMonkey that will cause my screen to repeatedly jump to the top of my screen when I click a button, and stop jumping when I click the button again.
This is my code:
var perpetualScroll = function () {
var scrolling = false;
var scroll = function () {
if (scrolling) {
window.scrollTo(0, 0);
}
};
var scrollDiv = document.createElement("div");
scrollDiv.id = "topScroll0x2a";
scrollDiv.innerHTML = '<a class="topScroll" onclick="scrolling = !scrolling;" style="display:block; position:fixed; bottom: 1em; right: 1em; color:#fff; background-color:#000; padding:.5em;" href="#">Start scroll</a>';
document.body.appendChild(scrollDiv);
var intervalId = window.setInterval(scroll, 50);
};
perpetualScroll();
When I click the button in the lower corner the script creates, it does jump to the top of the screen, but doesn't continue to perpetually do so.
I'm really new to Javascript and GreaseMonkey, so I'm not quite sure what the problem is. I suspect it might be due to issues in the onclick part of the link, but if it is, I can't seem to figure it out.

Doing onclick like that will not work like you expect. Your innerHTML is just a string, so JS has no idea that it is scoped within your perpetualScroll function.
onclick handlers that are strings are evaluated in the global scope, so what you have is equivalent to this:
window.scrolling = !window.scrolling;
The scrolling variable you want is different.
You should create an actual function like this:
var a = document.createElement('a');
a.className = (a.className || "") + ' topScroll';
a.style.display = 'block';
a.style.position = 'fixed';
a.style.bottom = '1em';
a.style.right = '1em';
a.style.color = '#FFF';
a.style.backgroundColor = '#000';
a.style.padding = '0.5em';
a.href = '#';
a.onclick = function(e){
scrolling = !scrolling;
return false;
};
scrollDiv.appendChild(a);
Obviously setting that CSS is terrible, so you should really put that in a separate stylesheet anyway.

Related

Can't use stopProgagation and preventDefault to stop opening a link

I can't seem to get preventDefault or stopPropagation to work on some types of links. I'd like to write a program to highlight an element on a webpage and save that element as I click it. I'd like to be able to click multiple elements on the page so the program should avoid navigate out of the page. The program fails in some cases. For examples, if I go to https://www.yahoo.com, past the program in the console log and click the ads image, it will open the link. The same happens when I visit https://www.amazon.com and click on the image above "Ad Feedback". It appears it just doesn't work on the ads links.
I tried this program on both firefox and chrome browser. The program works on majority of the links but fails on Ads link. By viewing the HTML source I can't figure out why it fails and how it can be fixed. The program is shown below. Just copy it to run in console.
var highlightDiv = document.createElement('div');
highlightDiv.id = 'testeditor123abc';
document.body.insertBefore(highlightDiv, document.body.firstChild);
var mouseX;
var mouseY;
document.addEventListener('mouseover', processElement, true);
document.addEventListener('click', captureElement, true);
function processElement(e) {
let elem = e.target;
let elemRect = elem.getBoundingClientRect();
highlightDiv.style.top = elemRect.top+'px';
highlightDiv.style.left = elemRect.left+'px';
highlightDiv.style.width = elemRect.width+'px';
highlightDiv.style.height = elemRect.height+'px';
highlightDiv.style.transition = '0.1s';
highlightDiv.style.background = 'rgba(0, 0, 255, 0.2)';
highlightDiv.style.borderColor = 'rgba(255, 0, 0, 0.8)';
highlightDiv.style.borderWidth = '2px';
highlightDiv.style.borderStyle = 'dashed';
highlightDiv.style.position = 'fixed';
highlightDiv.style.zIndex = '999999999999999';
highlightDiv.style.pointerEvents = 'none';
}
function captureElement(e) {
console.log('Mouse X: ', mouseX);
console.log('Mouse Y: ', mouseY);
let element = e.target;
let viewportDimensions = {};
viewportDimensions.height = document.documentElement.clientHeight;
viewportDimensions.width = document.documentElement.clientWidth;
let command = {};
console.log('Element:');
console.log(element);
e.preventDefault();
e.stopPropagation();
}
I hope the program would stop sending me to other page for any element I click on the page. I greatly appreciate any suggestion. Thanks.

.clone().appendTo - Replace element styles not working?

I have individual three arrows. on click; I want the div below them (letsChat) to change styles and I want to clone and append relevant information in that div. I also want it to revert back to it's original state when it is clicked again or if orientation is changed to portrait.
document.querySelector('#compositionArrow').onclick = function(){
var letsChat = document.querySelector('.lets-chat');
var letsChatButton = document.querySelector('.lets-chat a');
var compositionArrow = document.querySelector('#compositionArrow')
var compositionText = document.querySelector('.composition-text');
if (letsChatButton.style.display='flex' && window.matchMedia("(orientation: landscape)").matches) {
compositionArrow.style.transform='rotate(180deg)';
//letsChat.appendChild(compositionText).cloneNode(true);
//compositionText.clone().appendTo.letsChat; return false;
document.querySelector('.composition-text').clone().appendTo(document.querySelector('.lets-chat'));
letsChat.style.background='#00BCD4';
letsChatButton.style.display='none';
}
else if (letsChatButton.style.display='none' || window.matchMedia("(orientation: portrait)").matches){
compositionArrow.style.transform='rotate(180deg)';
letsChat.style.background='#ff8f00';
letsChatButton.style.display='flex';
}
}
example can be found below: (you may have to play with window
artpenleystudios.com
Here's something that demonstrates part of what you asked. It doesn't take into account orientation change, but it handles the click part. As far as I know, there's no straightforward way to detect orientation change, but here's an article that talks about a few options. Another idea would be to use jQuery Mobile as it fires orientationchange events.
So after much back and forth and after looking at your site more closely, this is what I managed to cobble together.
jQuery('#compositionArrow').click(function() {
var $letsChat = jQuery('.lets-chat');
var letsChat = $letsChat[0];
var letsChatButton = $letsChat.find('a')[0];
// Remove old composition text if it exists.
$letsChat.find('.composition-text').remove();
if (letsChatButton.style.display !== 'none' && window.matchMedia("(orientation: landscape)").matches) {
this.style.transform = 'rotate(180deg)';
$letsChat.append(jQuery('.composition-text').clone());
letsChat.style.background = '#00BCD4';
letsChatButton.style.display = 'none';
}
else if (letsChatButton.style.display === 'none' || window.matchMedia("(orientation: portrait)").matches) {
this.style.transform = '';
letsChat.style.background = '#ff8f00';
letsChatButton.style.display = 'flex';
}
});
It works for me in FireFox on a downloaded version of your site.
Cheers!

Remove iframe after printing

I'm new to HTML and Javascript. I'm trying to write a Javascript function to print the content of an (hidden) iframe in order to print documents (to the user, seemingly) without opening them.
I based the function on the example I found here: https://developer.mozilla.org/en-US/docs/Printing#Print_an_external_page_without_opening_it
Printing the content works fine but the trouble is removing the iframe from the document after the printing has finished. This is what my code looks like now.
function closePrint () {
var element = document.getElementById("printFrame");
element.parentNode.removeChild(element);
}
function setPrint () {
this.contentWindow.__container__ = this;
this.contentWindow.onbeforeunload = setTimeout(closePrint, 100);
this.contentWindow.onafterprint = setTimeout(closePrint, 100);
this.contentWindow.focus(); // Required for IE
this.contentWindow.print();
}
function printPage (sURL) {
var oHiddFrame = document.createElement("iframe");
oHiddFrame.onload = setPrint;
oHiddFrame.width = 0;
oHiddFrame.height = 0;
oHiddFrame.style.position = "fixed";
oHiddFrame.style.right = "0";
oHiddFrame.style.bottom = "0";
oHiddFrame.id = "printFrame";
oHiddFrame.src = sURL;
document.body.appendChild(oHiddFrame);
}
I changed two lines in the example from
this.contentWindow.onbeforeunload = closePrint;
this.contentWindow.onafterprint = closePrint;
to
this.contentWindow.onbeforeunload = setTimeout(closePrint, 100);
this.contentWindow.onafterprint = setTimeout(closePrint, 100);
As it didn't remove the iframes without the timeout.
This works fine in both IE11 and Chrome, but in IE compitability mode (which I think emulates IE7) it gives me an error "Not implemented" when I try to use setTimeout.
So my question is, is there another way to run the closePrint function after a timeout or some other way to remove the iframe from the document when I've printed the content? Any help is appreciated.
after printing, leave the iframe on document.body. When you need to add your next iframe, first run a check for its presence ~ if its present, remove it then (first two lines).
myfunction() {
const iframe = document.querySelector('iframe');
if (iframe) iframe.parentNode.removeChild(iframe);
const i = document.createElement('iframe');
i.style.display = 'none';
i.src = this.study.DocumentUrl;
document.body.appendChild(i);
document.querySelector('iframe').contentWindow.focus();
document.querySelector('iframe').contentWindow.print();
}

Javascript - Function works once, but never again

I'm building a very simple lightbox script; when you click a button, the lightbox is created. When you click on the lightbox background, it is removed.
The first time you call the function it works just fine. Click button, lightbox shows, click lightbox, it disappears. However, if you try to click the button AGAIN, nothing happens - the div isn't called. No console errors or anything, don't know what the problem is.
JSFIDDLE http://jsfiddle.net/3fgTC/
CODE
function closeLightBox(){
document.body.removeChild(lightBox);
}
function createElem(){
var elem = "<div id='lightBox'></div>";
var bodyElem = document.body;
bodyElem.innerHTML = elem + bodyElem.innerHTML;
var lightBox = document.getElementById("lightBox");
lightBox.style.width = "100%";
lightBox.style.height = "800px";
lightBox.style.backgroundColor = "rgba(0,0,0,.5)";
lightBox.onclick = function(){
closeLightBox();
}
}
var button = document.getElementsByClassName("btn");
for (var i = 0; i<button.length; i++){
button[i].onclick = function(){
createElem();
}
}
Any ideas?
Don't prepend to innerHTML; that makes the browser re-parse the HTML and re-create every DOM element, losing event handlers in the process. Instead, use document.createElement:
var lightBox = document.createElement('div');
document.body.insertBefore(lightBox, document.body.firstChild);
Furthermore, inline closeLightBox:
lightBox.onclick = function() {
document.body.removeChild(lightBox);
}
Try it.

A few javascript issues: strange time dependence and images not loading 1st time

I'm trying to create a script for creating an overlay containing an image and some text, but i've run into some problems
1st: the image in the overlay doesn't appear when first clicked, but does on subsequent openings.
2nd: the scrollTo function only works if put in a timeout, otherwise it appears to do nothing.
If anyone could shed any light on this, or any other mistakes i've made, it would be much appreciated.
javascript:
var scrollY;
var i_w;
var i_h;
function showOverlay(filepath,num){
scrollY = document.body.scrollTop || document.documentElement.scrollTop;
hideOverlay();
document.getElementById("num").innerHTML ="image #: " + num + " click image to close";
var preload = new Image();
preload.src = filepath;
i_w = preload.width;
i_h = preload.height;
document.getElementById("blowup").width = i_w;
document.getElementById("blowup").height = i_h;
document.getElementById("blowup").src = filepath;
document.getElementById("overlay").style.display = "inline";
setTimeout("window.scrollTo(0,scrollY)",1);
setOverlayBounds(); //a function to orient the overlay div.
}
html:
<div id="overlay">
<center>
<img id="blowup" src="#" onClick="javascript:hideOverlay()">
<br>
<p id="num"></p>
<br>
</center>
</div>
css:
#overlay
{
display:none;
position:absolute;
background-color:#999;
border:medium;
border-color:#0F0
}
You should use the load event for the image to make sure, it finished loading before you execute your code. Also, you shouldn't use strings in connection with setTimeout. It's better to pass the function directly:
var preload = new Image();
preload.src = filepath;
preload.onload = function() {
i_w = preload.width;
i_h = preload.height;
document.getElementById("blowup").width = i_w;
document.getElementById("blowup").height = i_h;
document.getElementById("blowup").src = filepath;
document.getElementById("overlay").style.display = "inline";
setTimeout(function(){window.scrollTo(0,scrollY);},1);
setOverlayBounds(); //a function to orient the overlay div.
};
This should at least fix your first issue.

Categories