Safari does not add a break when hitting enter - javascript

I want a user to be able to type in a content editable div, hit enter (or come to the end of the line) and have their text collected into a variable and have their cursor put on a new line, standard for any text editor. I have this event listner that checks for those conditions:
writerId.addEventListener('keydown', function(event){
if(event.key === "Enter" || document.getElementById("writer").offsetWidth >= "570") {
if(initialState === true) {
writtingContent = writerId.innerHTML;
blurId.innerHTML = writtingContent ;
writerId.innerHTML = "";
initialState = false;
} else {
writtingContent = writtingContent + writerId.innerHTML;
blurId.innerHTML = writtingContent ;
writerId.innerHTML = "";
}
}
});
The new line works in Chrome, FireFox but not Safari.
Initially I added this as a workaround for Safari:
if(navigator.userAgent.indexOf("Safari") != -1) {
writtingContent = writtingContent + "</br>";
console.log(navigator.userAgent);
}
But it broke things in other browsers (specifically Opera) and I've read that navigator.userAgent is not the best way to go about browser specific issues anyway.
I've seen some workarounds with feature detection but I'm not sure if that's necessary; I'd love if there was an easier way; something, perhaps, I've overlooked.

Related

Copy data to clipboard without selecting any text

Is there any cross-platform, or even mostly cross-platform, way to copy text to the clipboard in JavaScript without making an element, putting it on the page, and then selecting the text? How do the websites with "Copy to clipboard" buttons do it? I don't want it to use input fields because the idea is to copy anything into the clipboard, even stuff that may not be in an element.
I believe these days you can use navigator.clipboard if you only care about this working in modern versions of chrome, firefox, edge and opera.
https://developer.mozilla.org/en-US/docs/Web/API/Clipboard
e.g.
var amazingText = "Hello World! How sweet the content";
navigator.clipboard.writeText(amazingText);
Your best best for safari, ie,old browsers and anything else support is to check if navigator.clipboard is defined and have a fallback to the old inefficient create throw away element select and copy as a last resort.
I have used this mainly when there is a reasonably large about of data to copy to the clipboard as i have noticed performance issues with the select and exec methods.
Edit*
I briefly looked on the clipboard.js website as suggested and there is a sentence which says "This library relies on both Selection and execCommand APIs." which suggests perhaps it does not provide answer the question. However I have not looked at the source to verify this assumption.
https://clipboardjs.com/#browser-support
Hope this is what you looking for.
document.getElementById("copyButton").addEventListener("click", function() {
copyToClipboard(document.getElementById("txt"));
});
setInterval(function(){
document.getElementById("txt").innerHTML = "Copy Me!!! # " + new Date().getTime();
},1000);
function copyToClipboard(elem) {
// create hidden text element, if it doesn't already exist
var targetId = "_hiddenCopyText_";
var isInput = elem.tagName === "INPUT" || elem.tagName === "TEXTAREA";
var origSelectionStart, origSelectionEnd;
if (isInput) {
// can just use the original source element for the selection and copy
target = elem;
origSelectionStart = elem.selectionStart;
origSelectionEnd = elem.selectionEnd;
} else {
// must use a temporary form element for the selection and copy
target = document.getElementById(targetId);
if (!target) {
var target = document.createElement("textarea");
target.style.position = "absolute";
target.style.left = "-9999px";
target.style.top = "0";
target.id = targetId;
document.body.appendChild(target);
}
target.textContent = elem.textContent;
}
// select the content
var currentFocus = document.activeElement;
target.focus();
target.setSelectionRange(0, target.value.length);
// copy the selection
var succeed;
try {
succeed = document.execCommand("copy");
} catch(e) {
succeed = false;
}
// restore original focus
if (currentFocus && typeof currentFocus.focus === "function") {
currentFocus.focus();
}
if (isInput) {
// restore prior selection
elem.setSelectionRange(origSelectionStart, origSelectionEnd);
} else {
// clear temporary content
target.textContent = "";
}
return succeed;
}
input {
width: 400px;
}
<div id="txt">copy me!!!</div><br><br><button id="copyButton">Copy</button><br><br>
<input type="text" placeholder="Click here and press Ctrl-V to see clipboard contents">
You can try Clipboard.js, plenty of examples out there.

Javascript doesn't work in IE, works fine in everything else

I am new to JavaScript and tried putting together an FAQs section that limits the number of shown answers to just 1 at a time. The JavaScript is here (also live at http://indulge.cc/indulge.js). For the whole live site, check out http://www.indulge.cc. You will see in FF, Chrome, Safari, etc. that the FAQs bit works, but doesn't go in IE. Don't know what I missed. Syntax?
function showonlyone(shownanswer)
{
var faqswitcher = document.getElementsByTagName('div');
for (var x=0; x<faqswitcher.length; x++)
{
name = faqswitcher[x].getAttribute('class');
if (name == 'faqswitcher')
{
if (faqswitcher[x].id == shownanswer)
{
if (faqswitcher[x].style.display == 'block')
{
faqswitcher[x].style.display = 'none';
}
else
{
faqswitcher[x].style.display = 'block';
}
}
else
{
faqswitcher[x].style.display = 'none';
}
}
}
}
Get the class attribute by querying the className property, instead of going after the attribute.
name = faqswitcher[x].className;
It works as well in the other browsers, and older IE's require it.

Disappearing Menu Commands After User Input in Tampermonkey

Tampermonkey is an extension for Google Chrome that attempts to emulate the functionality of Greasemonkey. To be clear, I got my script to work in Chrome and the default JavaScript changes to show up. I wanted to test the menu commands, however, and entered a 6-digit hex color code after clicking on the command in the Tampermonkey menu. I reloaded the page, and the commands disappeared from the menu! My script was still there (and the checkbox was ticked).
No matter what I did or what code I changed, I could never emulate this initial functionality after that user-defined input was set. This leads me to believe that there's some persistent data that I can't delete that's causing my script to fail prematurely. NOTE: This exact script works perfectly and without errors in Firefox.
This is obviously not a Tampermonkey forum, but people here seem very knowledgeable about cross-platform compatility. I didn't hear a single peep from the Chrome console after all of the changes below, and I'm really just out of ideas at this point. Here are some things I've tried (with no success). Any console errors are listed:
Changing jQuery version from 1.5.1 to 1.3.2
Calling localStorage.getItem('prevoColor') from console after page load (both values null)
Changing client-side storage from localStorage to get/setValue
Calling GM_getValue from the console = ReferenceError: GM_getValue is not defined
Deleting localStorage entries for veekun.com in Chrome options
Refreshing, Re-installing the script, and restarting the browser more times than I can count
Repeating all of the above commands using Firebug Lite (bookmarklet)
Here's the code I was using:
// ==UserScript==
// #name Veekun Comparison Highlighter
// #namespace tag://veekun
// #description Highlights moves exclusive to pre-evolutions on veekun.com's family comparison pages (user-defined colors available)
// #include http://veekun.com/dex/gadgets/*
// #author Matthew Ammann
// #version 1.0.3
// #date 3/11/11
// #require http://sizzlemctwizzle.com/updater.php?id=98824
// #require http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js
// ==/UserScript==
/*
Goal: Change checkmark color & move name to user-specified color on family comparison pages if
[DONE] Baby poke has a LEVEL-UP move unlearned by any evolutions
[DONE] a) Make sure move is not a TM or tutor move
[DONE] Any other mid-evolution has a move unlearnable by a final evo (Caterpie, Weedle families)
[DONE] a) Make sure move is not a TM or tutor move
[DONE] Any pre-evo has a TUTOR move unlearned by any evo (Murkrow in HG/SS)
[] Implement auto-update after uploading to userscripts.org
Credits: Brock Adams, for helping with Chrome compatibility
Metalkid, for the jQuery consult
*/
var isLevelupMove = false;
var isTutorMove = false;
var isTM = false;
var TMhead = $('#moves\\:machine');
var hasSecondEvo = false;
var hasFinalEvo1 = false;
var hasFinalEvo2 = false;
var header = $('.header-row').eq(1);
var TMmoves = new Array();
//This section deals with the user-defined colors
GM_registerMenuCommand("Color for pre-evolutionary-only moves", prevoColorPrompt)
GM_registerMenuCommand("Color for first evolution-only moves", evoColorPrompt)
var prevoColor = GM_getValue('prevoColor', '#FF0000');
var evoColor = GM_getValue('evoColor', '#339900');
function prevoColorPrompt()
{
var input = prompt("Please enter a desired 6-digit hex color-code for pre-evolutionary pokemon:")
GM_setValue('prevoColor', '#'+input);
}
function evoColorPrompt()
{
var input = prompt("Please enter the desired 6-digit hex color-code for first-evolution pokemon:")
GM_setValue('evoColor', '#'+input);
}
//This loop tests each 'th' element in a sample header row, determining how many Evos are currently present in the chart.
$('.header-row').eq(1).find('th').each(function(index)
{
if($(this).find('a').length != 0)
{
switch(index)
{
case 2:
hasSecondEvo = true;
break;
case 3:
hasFinalEvo1 = true;
break;
case 4:
hasFinalEvo2 = true;
break;
}
}
});
//All 'tr' siblings are TM moves, since it's the last section on the page
//This array puts only the names of the available TMs into the TMmoves array
TMhead.nextAll().each(function(index)
{
TMmoves.push($(this).children(":first").find('a').eq(0).html());
});
$('tr').each(function(index)
{
var moveName = $(this).children(":first").find('a').eq(0).html();
moveName = $.trim(moveName);
switch($(this).attr('id'))
{
case 'moves:level-up':
isLevelupMove = true;
break;
case 'moves:egg':
isLevelupMove = false;
break;
case 'moves:tutor':
isTutorMove = true;
case 'moves:machine':
isTM = true;
}
if(isLevelupMove || isTutorMove)
{
var babyMoveCell = $(this).find('td').eq(0);
babyMoveText = $.trim(babyMoveCell.html());
secondEvoCell = babyMoveCell.next();
secondEvoText = $.trim(secondEvoCell.html());
finalEvo1Cell = secondEvoCell.next();
finalEvo1Text = $.trim(finalEvo1Cell.html());
finalEvo2Cell = finalEvo1Cell.next();
finalEvo2Text = $.trim(finalEvo2Cell.html());
//This checks if evolutions have checkmarks
if(babyMoveText.length > 0)
{
if(hasSecondEvo && secondEvoText.length == 0 || hasFinalEvo1 && finalEvo1Text.length == 0 ||
hasFinalEvo2 && finalEvo2Text.length == 0)
{
//See if the move is a TM before proceeding
var tm = tmCheck(moveName);
if(!tm)
{
if(secondEvoText.length > 0)
{
babyMoveCell.css("color", evoColor);
secondEvoCell.css("color", evoColor);
babyMoveCell.prev().find('a').eq(0).css("color", evoColor); //highlights move name
}
else
{
babyMoveCell.css("color", prevoColor);
babyMoveCell.prev().find('a').eq(0).css("color", prevoColor);
}
}
}
}
else if(secondEvoText.length > 0)
{
if(hasFinalEvo1 && finalEvo1Text.length == 0 || hasFinalEvo2 && finalEvo2Text.length == 0)
{
var tm = tmCheck(moveName);
if(!tm)
{
secondEvoCell.css("color", evoColor);
babyMoveCell.prev().find('a').eq(0).css("color", evoColor);
}
}
}
}
});
function tmCheck(input)
{
var isTM = false;
//Iterate through TMmoves array to see if the input matches any entries
for(var i = 0; i < TMmoves.length; i++)
{
if(input == TMmoves[i])
{
isTM = true;
break;
}
}
if(isTM == true)
return true;
else
return false;
}
//alert("evoColor: " + localStorage.getItem('evoColor') + ". prevoColor: " + localStorage.getItem('prevoColor'));
Any ideas as to why this is happening?
EDIT: I messaged sizzlemctwizzle about this problem, and this was his reply: "Tampermonkey’s #require implementation is incorrect. It downloads my updater far too often so I have banned it from using my updater via browser sniffing. My server just can’t handle the traffic it brings. The script it is downloading from my server shouldn’t have any actual code in it. Since it is causing errors with in your script I would guess Tampermonkey isn’t passing the User Agent header when it does these requests. I’m never tested my updater in Chrome so I have no idea why it breaks. Perhaps you could try and install NinjaKit instead."
What URL are you testing this on? I tested on http://veekun.com/dex/gadgets/stat_calculator.
Anyway, the script behavior, vis à vis the menu commands did seem erratic with Tampermonkey. I couldn't really tell / didn't really check if the rest of the script was working as it should.
The culprit seems to be the sizzlemctwizzle.com update check. Removing its // #require made the menu stable. Putting that directive back, broke the script again.
I've never been a fan of that update checker, so I'm not going to dive into why it appears to be breaking the Tampermonkey instance of this script. (That would be another question -- and one probably best directed at the 2 responsible developers.)
For now, suggest you just delete it. Your users will check for updates as needed :) .

Blinking document.title and IE7 (no way ?)

i develop a website and i need let the document title blinking when the browser lost the focus to get the attention from the user.
This is a common task for example in some social network. Btw my javascript code work fine in Chrome, Firefox, Opera, but not in IE7 (that i am testing before release the site)
IE7 have a strange behavior because if i print the document.title in a debug text (you can see in the code), it's changed but the browser still show the previous document title
I try to search a lot on internet to try to fix this problem but with no luck so i decided to post the question in this site. Here my javascript code below and thanks in advance for the suggestions.
the JS method is called by this.blink(true)
// other methods above and below ....
this.blink = function(Action)
{
if (Action)
{
if (!this.blinking)
this.oldTitle=top.document.title;
else
clearInterval(this.blinkTimer);
// debug current title
$('debugText').value = 'ORIGINAL ' + top.document.title + '\n' + $('debugHistory').value;
this.blinkTimer = setInterval(function() {
var msg='MSG', newTitle
if (top.document.title == msg)
newTitle = '----';
else
newTitle = msg;
// assign title
top.document.title = newTitle;
// debug blinking, is really changed but not shown <---
$('debugText').value = 'BLINK ' + top.document.title + '\n' + $('debugHistory').value;
}, 1000);
}
else
{
clearInterval(this.blinkTimer);
if (this.blinking)
top.document.title = this.oldTitle;
}
this.blinking = Action;
}
If you're using jQuery, I've made a plugin called Title Alert for the purpose of blinking notification messages in the browser title bar. With it, you can specify different options like duration, blinking interval, if the blinking should stop when the window/tab gets focused, etc. I've verified that the plugin works in IE6, IE7, IE8, Firefox, Chrome and Safari.
Here is an example on how to use it:
$.titleAlert("New chat message!", {
requireBlur:true,
stopOnFocus:true,
interval:600
});
If you're not using jQuery, you might still want to look at the source code (there are a few quirky bugs and edge cases that you need to handle when doing title blinking if you want to fully support all major browsers).
Instead of top.document.title try top.document.getElementsbyTagName('title')[0] (This is assuming top is some form of frame or window)
Try this in IE
this.blink = function (Action)
{
if (Action)
{
if (!this.blinking)
this.oldTitle=top.document.title;
else
clearInterval(this.blinkTimer);
this.blinkTimer = setInterval(function() {
var msg='MSG', newTitle
if (top.document.title == msg)
newTitle = '----';
else
newTitle = msg;
// assign title
top.document.title = newTitle;
}, 1000);
}
else
{
clearInterval(this.blinkTimer);
if (this.blinking)
top.document.title = this.oldTitle;
}
this.blinking = Action;
}
window.blink('now');​​​​
Mostly it will be an issue that window.onblur etc. is not triggering your blink function. If the above works, then you can use mouse movement to track timeout.

RadEditor scrolls to top after pasting the contents

I am using Telerik RadEditor.
The issue:
On pasting the content into the Telerik Radeditor, the editor is getting scrolled to top. So, I searched the internet and also Telerik forums, but no luck. Finally, I worked on the following code with fix.
Code for RadEditor Server-Side Control:
<telerik:RadEditor
ID="E"
runat="server"
Width="100%"
AllowScripts="true"
AllowPaging="true"
EnableResize="false"
NewLineMode="P"
OnClientLoad="OnClientLoad"
OnClientModeChange="E_OnClientModeChanged"
EditModes="Design,Html"
StripFormattingOptions="Span,MsWordRemoveAll,CSS,Font,ConvertWordLists"
OnClientPasteHtml="radEditorControl_OnClientPasteHtml"
OnClientSelectionChange="OnClientSelectionChange">
</telerik:RadEditor>
Below is the Javascript Code with fix:
//Event on pasting the content into the RadEditor. Fixing the scrolling issue on pasting the content.
var isPasted = false;
function radEditorControl_OnClientPasteHtml(editor, args) {
if (editor != undefined)
isPasted = true;
}
function OnClientSelectionChange(editor, args) {
if (isPasted != undefined && isPasted == true && editor != undefined) {
isPasted = false;
editor.setFocus();
var iframeElement = editor._contentAreaElement; // the DOM element for the iframe;
if (iframeElement) {
//Get the iFrame cursor position.
var _focusNode = iframeElement.contentWindow.getSelection().focusNode;
if (_focusNode != undefined) {
//Focus node is not an element, get the previous element sibling
if (_focusNode.nodeType != 1) {
if (_focusNode.previousElementSibling != undefined)
_focusNode = _focusNode.previousElementSibling;
else
_focusNode = _focusNode.parentNode;
}
//Insert a div near focusNode(cursor) of the iFrame contentWindow.
var timeStamp = new Date().getUTCMilliseconds();
var _id = "scrollArea_" + timeStamp;
var focusElement = jQuery('<input type="text" id="' + _id + '" name="' + _id + '" onfocus="alert();" />').insertAfter(_focusNode)[0];
setTimeout(function () {
if (focusElement != undefined) {
focusElement.focus({ preventScroll: true });
focusElement.select();
var range = editor.getSelection().getRange(true); //returns an object that represents a restore point.
editor.getSelection().selectRange(range);
if (range != undefined && range.collapse !=undefined)
range.collapse(true);
jQuery(focusElement).replaceWith("");
}
}, 50);
}
}
}
}
The above code is working in IE and Chrome, but not in Firefox as focus() is not getting triggered for the input element which I am binding.
Please let me know if there is any other way for resolving the scroll issue on paste in RadEditor.
I am aware of such a problem within the older versions of RadEditor. My advice is to try the latest version which you can test at https://demos.telerik.com/aspnet-ajax/editor/examples/overview/defaultcs.aspx. If the problem still persists please drop us a line in the Telerik AJAX forums or via the support ticketing system and we will look deeper into it.

Categories

Resources