Why JS if() function not executing in safari? - javascript

I have this code, which displays or hides text blocks according to the button pressed. The menu is from two buttons, and when one button is pressed it triggers the text to be displayed and hides another text.
The code works fine on chrome, but on safari, only the first piece of code works (the one which adds a new class to the button). What could be an issue here?
I tried to test by printing the button text (just before alert("The browser shows this alert");) and the code prints button text correctly. But I can't get into the if().
$(".about-us-button1").on('click', function () {
$(".about-us-button1").removeClass('active');
var button = $(this);
$(this).addClass('active');
for (var i = 0; i < button.length; i++) {
var name = button[i].innerText;
alert("The browser shows this alert");
if (name === 'Cargo booking form' || name === 'Krovinių užsakymo forma' || name === 'ЗАКАЗ') {
alert('The browser not reaching this piece of code');
$(".cargo-booking").addClass('visible');
$(".request-cargo").removeClass('visible');
}
if (name === "Request about cargo" || name === "Užklausa apie krovinį" || name === "Запрос Стоимости") {
$(".cargo-booking").removeClass('visible');
$(".request-cargo").addClass('visible');
alert('The browser not reaching this piece of code');
}
}
});
After running the command console.log(escape(name)) I got a different results at Chrome: Request%20about%20cargo and Safari: <h2>Request about cargo</h2>
I can't find a simple way to get a text from an HTML object, that works on all browsers.

try to change
var name = button[i].innerText;
to this:
var name = button[i].textContent;

Related

javascript error in copy content to clipboard [duplicate]

I am working on a bookmark app where i have to store the user's selected keywords or words or content. I am using the createRange() and addRange() javascript methods to create the range and then find out the selected elements/contents by the user. The code i written for this is as follow.
<head>
<script type="text/javascript">
var storedSelections = [];
function StoreSelection () {
if (window.getSelection) {
var currSelection = window.getSelection ();
for (var i = 0; i < currSelection.rangeCount; i++) {
storedSelections.push (currSelection.getRangeAt (i));
}
currSelection.removeAllRanges ();
} else {
alert ("Your browser does not support this example!");
}
}
function ClearStoredSelections () {
storedSelections.splice (0, storedSelections.length);
}
function ShowStoredSelections () {
if (window.getSelection) {
var currSelection = window.getSelection ();
currSelection.removeAllRanges ();
for (var i = 0; i < storedSelections.length; i++) {
currSelection.addRange (storedSelections[i]);
}
} else {
alert ("Your browser does not support this example!");
}
}
</script>
</head>
<body>
Select some content on this page and use the buttons below.<br /> <br />
<button onclick="StoreSelection ();">Store the selection</button>
<button onclick="ClearStoredSelections ();">Clear stored selections
</button>
<button onclick="ShowStoredSelections ();">Show stored selections</button>
</body>
This code is working perfectly on Firefox. I am able to select multiple things one by one and able to show the selected content again but on chrome and chromium i am getting Discontiguous selection is not supported. error when i store more than one elements in range array and click on show stored selections button.
Help will be appreciated. And please suggest me if there is some other alternatives do accomplish this bookmarking task.
Write
window.getSelection().removeAllRanges();
immediately before creating range.
https://bugs.chromium.org/p/chromium/issues/detail?id=399791
Here's the only possible way of doing this that I was able to come up with:
Wrap the selection in <span style="background: Highlight;">...</span>.
But note:
Obviously, you have to remove those spans again as soon as anything else is selected, but that shouldn't be too difficult. However, you should use window.onmousedown for that rather than window.onclick, because onclick is fired after any button is pressed, so when pressing your "Show stored selections" button, a new selection will be created, thus destroying the one that was supposed to be captured.
Removing or replacing any elements in which a stored selection starts or ends will invalidate that selection, so when clicking "Show stored selections", nothing will show up.
If the selection spans over multiple elements, it needs to split up into one selection for each element, otherwise inserting the span will either fail or cut other elements (like buttons) in half.
The following code (fiddle) is the best I was able to do:
var storedSelections = [];
var simulatedSelections = [];
window.onmousedown = clearSimulatedSelections;
function storeSelection()
{
if(window.getSelection)
{
var currSelection = window.getSelection();
for(var i = 0; i < currSelection.rangeCount; i++)
{
storeRecursive(currSelection.getRangeAt(i));
}
currSelection.removeAllRanges();
}
else
{
alert("Your browser does not support this example!");
}
}
function storeRecursive(selection, node, started)
{
node = node || document.body;
started = started || false;
var nodes = node.childNodes;
for(var i = 0; i < nodes.length; i++)
{
if(nodes[i].nodeType == 3)
{
var first = nodes[i] == selection.startContainer;
var last = nodes[i] == selection.endContainer;
if(first)
{
started = true;
}
if(started)
{
var sel = selection.cloneRange();
if(!first)
{
sel.setStartBefore(nodes[i]);
}
if(!last)
{
sel.setEndAfter(nodes[i]);
}
storedSelections.push(sel);
if(last)
{
return false;
}
}
}
else
{
started = storeRecursive(selection, nodes[i], started);
}
}
return started;
}
function clearStoredSelections()
{
storedSelections = [];
}
function showStoredSelections()
{
if(window.getSelection)
{
var currSelection = window.getSelection();
currSelection.removeAllRanges();
for(var i = 0; i < storedSelections.length; i++)
{
var node = document.createElement("span");
node.className = "highlight";
storedSelections[i].surroundContents(node);
simulatedSelections.push(node);
}
}
else
{
alert("Your browser does not support this example!");
}
}
function clearSimulatedSelections()
{
for(var i = 0; i < simulatedSelections.length; i++)
{
var sec = simulatedSelections[i];
var pn = sec.parentNode;
while(sec.firstChild)
{
pn.insertBefore(sec.firstChild, sec);
}
pn.removeChild(sec);
}
simulatedSelections = [];
}
.highlight
{
background: Highlight;
}
Select some content on this page and use the buttons below.<br><br>
<button onclick="storeSelection();">Store the selection</button>
<button onclick="clearStoredSelections();">Clear stored selections</button>
<button onclick="showStoredSelections();">Show stored selections</button>
It works in Firefox, Safari and Chrome, but has the following shortcomings:
Selections over multiple lines don't select the blank area between the end of the line and the border of the parent element, like actual selections do.
Sometimes when starting a selection at a point before the start of a stored selection, displaying them will merge the ranges, so the text in between is selected too. Sorting the array of stored selections doesn't seem to help.
In Safari, the tab crashed multiple times with a segmentation fault when selecting multiple lines and ending/starting a selection in the middle of a button's text.
However, I doubt that anything better is possible in browsers other than Firefox, but even Firefox has a ticket to drop discontiguous selections.
FYI I was getting a similar error when rolling my own "copy to clipboard" feature. I'm not going to address OP's provided code, but I'll tell you how I fixed it in my own code.
Reproduce:
Copy some other text on the page to the clipboard, e.g. "foo".
Paste the text somewhere. It outputs "foo".
Click your "copy to clipboard" button, which copies e.g. "bar".
Paste the text somewhere.
Expected:
"bar" is outputted.
Actual:
"Discontiguous selection is not supported"
Fix:
Call window.getSelection().removeAllRanges() at the start of your "copy to clipboard" event handler. "Discontiguous" means "not connected". So my guess is that the browser copies the first range (the node containing "foo"), and then gets angry when you try to select another range that is not next to the first node.

Making the search field (with results) disappear when clicking outside on Ipad

I have two html elements as follows :
A input element whose class is "fts-input". This input serves as a search box.
A div container, containing all the list of results, whose class is "dropdown-items-wrapper"
I made a code who worked in all browsers except Safari, that made the search results disappear when clicking outside of the search field, or outside of the search results. This code is :
var ftsInput = $('.fts-input');
var dropDownList = $('.dropdown-items-wrapper');
function closeSearchWhenClickingElsewhere(event, dropDown) {
var clickedElement = event.target;
if (!clickedElement) return;
var elementClasses = clickedElement.classList;
var clickedOnSearchOrResults = elementClasses.contains('fts-input') ||
elementClasses.contains('dropdown-items-wrapper');
if(!clickedOnSearchOrResults) {
dropDown.fadeOut('slow');
}
}
$document.on('click', (e) => {
this.closeSearchWhenClickingElsewhere(e, dropDownList);
});
But this code seems to not work on Ipad (iOs Safari). Do you have a clue why it isn't working ?
You have to wrap around document within the $ jQuery symbol.
So your code becomes,
$(document).on('click', (e) => {
this.closeSearchWhenClickingElsewhere(e, dropDownList);
});
Alternatively, you can assign as this:
$document = $(document);
Created a fiddle for you which works fine on Safari 10: https://jsfiddle.net/1ymrtcbf/

Textarea and radio buttons visibility issues

So what I'm trying to do is basically check if the response from the server contains alternatives. If it does then it should print the alternatives out , hide the text area where I would answer the question if the question did not contain alternatives and show the radio buttons. Problem is, it prints out the response, but never hides/shows the text area or the radio buttons.
I tried putting the code for the visibility in a button to see if it works on click, and it does, but it does not work when I put the same code in the if statement.
Also, another problem is that instead of printing out the actual alternatives, it just prints out Object object, but when I try to print out the question, it prints it out correctly.
HideAllRadios and ShowArea functions are basically the same as what's in the if statement, but reversed.
Here is the code:
QuestionReq.onreadystatechange = function(){
if(QuestionReq.readyState === 4 && QuestionReq.status === 200) {
response = JSON.parse(QuestionReq.responseText);
console.log(response);
questionLink.innerText = response.question;
url = response.nextURL;
// questAltLink.innerText = response.alternatives;
if(response.alternatives !=null){
questAltLink.innerText = response.alternatives;
AnswerArea.style.visibility = "hidden";
RadioArea.style.visibility = "visible";
}
HideAllRadios();
ShowArea();
}
Here is how they are declared:
var questions = function () {
var AnswerArea = document.getElementById("AnswerArea");
var RadioArea = document.getElementById("radioplace");

Javascript - Submit Text Field, Show Div, Hide All Others

I have a simple form (text field and submit button). I am trying to have the user submit a number, and the resulting number will display one div (from a set of divs).
I tried using this example as a base (when the user clicks a link, it shows a div, but hides others).
My test is below:
var divState = {};
function showhide(oFrm) {
var dividnum = oFrm.Inputed.value;
var prepar = "para";
var divid = prepar + theInput; /* should result in something like "para52" */
divState[divid] = (divState[divid]) ? false : true;
//close others
for (var div in divState){
if (divState[div] && div != divid){
document.getElementById(div).style.display = 'none';
divState[div] = false;
}
}
divid.style.display = (divid.style.display == 'block' ? 'none' : 'block');
}
http://jsfiddle.net/LfzYc/431/
Note: I am NOT proficient in JavaScript at all, which is why I am having difficulty.
Also, I'd like to add a function ... if the number entered is not between 1-4, show a different div, maybe with the id paraEnd.
Please look at the jsFiddle based on your one. I hope I've done what you want. I changed the showhide function and your HTML (fixed div's IDs and added one more div#paraEnd). I'd suggest you refactoring your code.
You should use jQuery to have an easy way to manipulate the DOM.
Using jQuery I made an example for you, just change your JS and paste mine:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">
(function ($) {
// get the paragraphs
var paragraphs = $('.paragraph');
// form submit
$('#paragraphform').submit(function (e) {
// prevent the event to flow
e.preventDefault();
// get the input value
var value = $('#Inputed').val() - 1;
// reset all divs removing active css class
paragraphs.removeClass('active');
$('.error').removeClass('active');
// verify if the value doens't exist
if(value < 0 || value > paragraphs.length - 1) {
$('.error').addClass('active');
return;
}
// show the active div
paragraphs.eq(value).addClass('active');
});
})(jQuery);
</script>
Is that what you need?
If you not familiar with jQuery, this is the jquery Learn Center:
https://learn.jquery.com/
And this is a nice tutorial for beginners:
http://www.tutorialspoint.com/jquery/

onload function revision to check value of a form

I am working on a website and I came across an interesting situation. In this particular website we are using a form that has given fields filled out that can be modified, etc. Part of this form gives the user the option between choosing one language or up to 6 languages. Each of these particular rows of the form are hidden unless the user clicks an add language button. There is also a remove language button. The problem that I am having is that there is an onload function that someone wrote to display the table on the my account page, but it only goes through and omits the sections of the table that are set to display:none; Here is the code for the current onload function:
<script type="text/javascript">
/* call onload with table id(s) */
function TR_set_toggle()
{
/* toggleRow method */
var toggleRow = function()
{
this.style.display = ((this.style.display == '') ? 'none' : '');
return false;
}
for (var oTable, a = 0; a < arguments.length; ++a)
{
oTable = document.getElementById(arguments[a]);
var r = 0, row, rows = oTable.rows;
while (row = rows.item(r++))
row.toggle = toggleRow;
}
}
onload = function()
{
TR_set_toggle('my_table');
}
</script>
It looks a little sloppy to me but maybe that's because I am new to javascript. Anyways, I want to change the function so it loads the table but also goes through each of the items that display none and check to see if they have input or not to display them. I don't understand the syntax of this.style.display = ((this.style.display == '') ? 'none' : ''); 1. How can I add an if statement into this line of code? 2. How can I check to see if a field has input or is set to the default? Any help is appreciated. Thanks.
How can I add an if statement into this line of code?
((this.style.display == '') ? 'none' : '');
is similar to
if( this.style.display == '' ) {
this.style.display == 'none'
}
else {
this.style.display = '';
}
How can I check to see if a field has input or is set to the default?
I dont understand your question. What do you mean with "field"?

Categories