I use a WordPress plugin to add via shortcodes one, two or three 'fontsampler' objects per specific page that each incorporate a text box and a font select box per fontsampler object. The JavaScript hides all select boxes via CSS except the last one.
In Chrome and Edge there is never any problem but in Firefox mostly all the select boxes show and sometimes just the last (F5 always shows all select boxes, ctrl F5 gives variable results).
The webserver also uses Litespeed cache and goes via Cloudfare CDN but I can't see this is relevant since only a Firefox issue.
NB I also tried the code and just the plugin on a vanilla wordpress test server (so no server caching) and didn't see the issue so I'm not sure how to proceed.
Here is the code if this helps:
jQuery(document).ready(function( $ ){
$("body").on("fontsampler.event.afterinit",".fontsampler-wrapper" , function () {
// ‘this’ is div.fontsampler-wrapper.initialized NB all 3x fontsamplers are initialised on first event but not drawn on page e.g. fontpickers (event fires up to three times)
//first count the number of fontsamplers on the page
var fsCount = $($(document).find(".fontsampler-interface")).length;
//check to see if last fontsampler has fully initialised (painted elements on page) else end event and wait for next
var fsStub=".fontsampler-id-";
var fsLast=fsStub+fsCount;
if ($($(document).find(fsLast)[0]).find(".fontsampler-ui-block.column.fontsampler-ui-block-fontpicker")[0] !== undefined) {
var fontsampler2Exists = $(document).find(".fontsampler-id-2").val();
var fontsampler3Exists = $(document).find(".fontsampler-id-3").val();
if (fontsampler3Exists !== undefined) {
//Three lines
// $(fs).find(".fontsampler-ui-block.column.fontsampler-ui-block-fontpicker")[0].style.display='none';
$($(document).find(fsStub+1)[0]).find(".fontsampler-ui-block.column.fontsampler-ui-block-fontpicker")[0].style.display='none';
$($(document).find(fsStub+2)[0]).find(".fontsampler-ui-block.column.fontsampler-ui-block-fontpicker")[0].style.display='none';
}
else if (fontsampler2Exists !== undefined) {
// Two lines
$($(document).find(fsStub+1)[0]).find(".fontsampler-ui-block.column.fontsampler-ui-block-fontpicker")[0].style.display='none';
}
else {
// One line so don't hide any font picker
}
}
Related
this is my very first question on Stackoverflow. I am currently developing a print function in my sap ui5 app to print out certain UI controls. I've got the function from here: http://embed.plnkr.co/jjyEPa1updkjBiNZqumS/preview
However, during runtime, when I click on the print button, my app only jumps to the method once and executes it correctly (to print). But after that, I can press the printbutton as often as I want, nothing happens and I can't find out why.
what the method does: i replace the body with a temporary body, which only contains the elements to be printed and execute window.print(). afterwards i insert the original body content again. Of course I use the UI controls to grab the HTML tags.
onPrintChart: function(oEvent){
var oTarget = this.getView(),
sTargetId = oEvent.getSource().data("targetId");
if (sTargetId) {
oTarget = oTarget.byId(sTargetId);
}
if (oTarget) {
var $domTarget = oTarget.$()[0],
sTargetContent = $domTarget.innerHTML,
sOriginalContent = $(document.body)[0].innerHTML;
$(document.body)[0].innerHTML = sTargetContent;
window.print();
$(document.body)[0].innerHTML = sOriginalContent;
} else {
jQuery.sap.log.error("onPrint needs a valid target container [view|data:targetId=\"SID\"]");
}
}
I managed to do it in a different, more elegant way without using a temporary body. I used CSS to hide all irrelevant elements (display: none) and keep only the relevant element for printing.
Apparently ui5 hung up when replacing the original body temporarily with another body. I noticed that ALL buttons didn't work anymore, not only the print button.
I have some custom JavaScript on my SquareSpace site that manipulates Product titles beyond what you can do with SquareSpace's default style editor. It works when initially loading the page (https://www.manilva.co/catalogue-accessories/) but if you click on any of the categories on the left, the styling resets to the default.
I'm assuming the JavaScript is being overwritten by the SquareSpace style, but I can't figure out why. Perhaps I'm calling the function in the wrong place?
Any suggestions would be helpful.
Thanks!
Current code:
document.querySelectorAll(".ProductList-filter-list-item-link".forEach(i=>i.addEventListener("click", function()
{
var prodList = document.querySelectorAll("h1.ProductList-title");
for (i = 0, len = prodList.length; i < len; i++)
{
var text = prodList[i].innerText;
var index = text.indexOf('-');
var lower = text.substring(0, index);
var higher = text.substring(index + 2);
prodList[i].innerHTML = lower.bold() + "<br>" + higher;
});
The source of your problem is that your template has AJAX loading enabled. There are currently a couple generally-accepted ways to deal with this as a Squarespace developer:
Disable AJAX loading
Write your javascript functions in a
manner that will run on initial site load and whenever an "AJAX load" takes place.
Option 1 - Disable AJAX:
In the Home Menu, click Design, and then click Site Styles.
Scroll down to Site: Loading.
Uncheck Enable Ajax Loading.
Option 2 - Account for AJAX in Your JS
There are a number of ways that developers approach this, including the following, added via sitewide code injection:
<script>
window.Squarespace.onInitialize(Y, function() {
// do stuff
});
</script>
or
<script>
(function() {
// Establish a function that does stuff.
var myFunction = function() {
// Do stuff here.
};
// Initialize the fn on site load.
myFunction();
// myFunction2(); , etc...
// Reinit. the fn on each new AJAX-loaded page.
window.addEventListener("mercury:load", myFunction);
})();
</script>
or
<script>
(function() {
// Establish a function that does stuff.
var myFunction = function() {
// Do stuff here.
};
// Initialize the fn on site load.
myFunction();
// Reinit. the fn on each new AJAX-loaded page.
new MutationObserver(function() {
myFunction();
// myFunction2(); , etc...
}).observe(document.body, {attributes:true, attributeFilter:["id"]});
})();
</script>
Each of those works for most of the latest (at time of writing) templates most of the time. Each of those have their advantages and disadvantages, and contexts where they do not work as one might expect (for example, on the /cart/ page or other "system" pages). By adding your code within the context of one of the methods above, and ensuring that the code is of course working in the desired contexts and without its own bugs/issues, you will have your code run on initial site load and on each AJAX page load (with some exceptions, depending on the method you use).
Your problem is the page does not reload when clicking a button on the left, just some elements are removed, added and replaced. The changed elements will not be restyled. You will need to re-run your JavaScript after one of those buttons is clicked. Perhaps something like this:
document.querySelectorAll(
".ProductList-filter-list-item"
).forEach(
i=>i.addEventListener(
"click", ()=>console.log("hello")
)
)
where you replace console.log("hello") with whatever resets your formatting.
The following (very simple, not fantastic) JS script is being used in one of my client's Bigcommerce carts. It's designed to pick up a given BC customer group, and check the status of a given element (a radio button), then either show a given selector, or let it remain hidden. It works fine in every browser except IE, where it runs as normal, but never shows the selector, even when the console shows no errors. (Why is it running on a one-second interval? Because BC loads the cart four pieces at a time, but from the same page. Whee!)
Is there a JS function being used here that IE doesn't support? I've reviewed all the functions, and I'm not seeing anything, but you know how blind you can get from staring at the same code for a few hours.
[edit: It appears IE is picking up the keyphrase in the script, even though innerText isn't supposed to do that. But at least I'm a step closer to a solution!]
<script>
window.onload = setInterval(hideCC, 1000);
function hideCC ()
{
/* Hide CC payment option for below listed groups only */
/* Add new customer groups with comma-separated list (i.e. [39,42,87]) */
var customergroup = [27,32,22,65,2,69,72,74,79,78,87,84,60,61,52,53,54,55,56,57,58,59,62,63,70,83,8,5];
/* Hide CC payment option for those using International Freight */
var intlFreight = document.documentElement.innerText.indexOf('International Freight');
/* Check state of wire transfer button; if it's checked, we don't need to do any of this */
var wireChecked = document.getElementById("radio-bankdeposit").checked;
if (wireChecked == true) {
return;
}
else {
/* If the customergroup belongs to one of those listed above OR the text "International Freight" appears on the page, that will trigger this if */
if(customergroup.indexOf({{{customer.customer_group_id}}}) > -1 || intlFreight > -1 ) {
/* console.log({{{customer.customer_group_id}}}); */
document.querySelector("#micro-app-ng-checkout > div > div > main > ol > li.checkout-step.checkout-step--payment.optimizedCheckout-checkoutStep > div.checkout-view-content > form > fieldset:nth-child(1) > div > ul > li.form-checklist-item.optimizedCheckout-form-checklist-item.form-checklist-item--selected.optimizedCheckout-form-checklist-item--selected").style.display="none";
}
}
};
</script>
Here's the jQuery version of checking for the string within the "shippingOption-desc" class. Hopefully this will get around the issue with IE and innerText :)
var intlFreight = $('.shippingOption-desc').text().indexOf('International Freight');
I have added a Select all / deselect all wrapper round a Select2 multi select control.
It works by looping through the options, pushing the values into an array then passing the array to the selct2 val as follows:
mySelect2.select2("val", mySelectedValuesArray);
This works fine in Chrome and in cases where there are not so many options to be selected. But in IE8 where they might be 100+ options the browser freezes as it attempts to render the selected values and I get multiple Stop Running this Script? alerts. I have had similar problems with IE8 when using expandable text boxes where the browser freezes whenever it has to increase the height of the textbox and assume its a quirk of the IE rendering engine. Anyway, in this case it renders the page unusable whenever you select all with anything more than 30 or 40 options.
I have tried creating the markup for the selected options container manually so as to just add it in one go, but, aside form then having to manually wire up the click events on each one to be able top remove them, Im finding when the selects change event fires it, select2 ends up removing the options anyway and i cant find a way round this.
Any ideas?
As an update here is my code
$(".filterIconContainer .filtericon").on("click",function () {
var $this = $(this);
var $associatedSelect = $("#" + $this.attr("data-associated-select"));
if ($associatedSelect.length == 0) {
$associatedSelect = $("#filterContainer div[data-tabid='" + $("#filterTabs li.active").attr("id") + "'] select");
}
if ($this.attr("data-action") == "select") {
var selected = [];
$associatedSelect.find("option").each(function (i, e) {
selected.push($(e).attr("value"));
});
setTimeout(function() {
$associatedSelect.select2("val", selected); // Browser throws stop running this script alert during select2 processing this line
$associatedSelect.change(); // call the change event to force any post change action
},5);
}
else {
$associatedSelect.select2('val', '');
$associatedSelect.change(); // call the change event to force any post change action
}
});
In the end I fixed this by making a change to the select2.js file
$(data).each(function () {
var i = this;
setTimeout(function () {
self.addSelectedChoice(i);
}, 0);
});
Wrapping the call to addSelectedChoice in a setTimeout allows IE to render the change without throwing a slow running script error.
So I've read just about everything I could find on MDN, stackoverflow, etc, and it all seems to be outdated and/or not working. Here is the issue:
I want to automatically put my extension's "toolbarbutton" on the nav-bar when it is installed, similar to Chrome. What the user does after that point is up to them, although if you remove the button (with this particular extension) you might as well just remove the extension as it's useless without the button. ANYWAY...
There seems to be two methods for doing this. You can append it to the "currentSet" and make it persist, like this:
var currentset = document.getElementById("nav-bar").currentSet;
currentset=currentset + ",MYBUTTON_ID";
document.getElementById("nav-bar").setAttribute("currentset",currentset);
document.getElementById("nav-bar").currentSet = currentset;
document.persist("nav-bar","currentset");
Or, you can use "insertItem" like this:
var toolbar = document.getElementById("nav-bar");
toolbar.insertItem("MYBUTTON_ID", null);
toolbar.setAttribute("currentset", toolbar.currentSet);
document.persist(toolbar.id, "currentset");
Now, if I use the first method, it works, but it completely erases everything else on the nav bar for some reason. "currentSet" doesn't seem to have the other nav-bar buttons on it when it goes to overwrite it, and so I just end up with the default nav-bar plus my icon. Wiping out all of a user's other buttons is no good...
The second option doesn't wipe out the other options, but for whatever reason, the "insertItem" way of doing it doesn't work at all. My button never appears in the nav-bar, period.
Any ideas?
Alright, like I thought, there was nothing wrong with my code, and the problem was exactly as I described.
When the extension is loaded and the script to install the button is executed, it's done too early. At the time of execution, "currentSet" only contains the default buttons. No other extension buttons are loaded yet. As a result, if you modify the currentSet and save (persist) it, you wipe out all other buttons.
The solution (for me) was to force my "install" script to wait longer. I found that once the page had been loaded, all of the other buttons had enough time to appear. So, I simply did this:
function installButton() {
var navbar = document.getElementById("nav-bar");
var newset = navbar.currentSet + ",MYBUTTONID";
navbar.currentSet = newset;
navbar.setAttribute("currentset", newset );
document.persist("nav-bar", "currentset");
}
window.addEventListener("load", function () { installButton(); }, false);
well I use this code to add toolbar button in navbar, but this works only for the first time for the fresh installation and not for the next installation i.e. upgrading of the addon as user can move/drag the icon to different location. So, you need to try this in the new firefox profile. Here is the code:
//plcae toolbar icon
var navbar = document.getElementById("nav-bar");
var newset = navbar.currentSet + ",MYBUTTON_ID";
navbar.currentSet = newset;
navbar.setAttribute("currentset", newset );
document.persist("nav-bar", "currentset");
and here is the code for XUL Overlay:
<toolbarpalette id="BrowserToolbarPalette">
<toolbarbutton id="MYBUTTON_ID" inserbefore="searchBar" class="toolbarbutton-1 chromeclass-toolbar-additional"
label="MYBUTTON_ID" tooltiptext="MYBUTTON_ID"
onclick="MYBUTTON_ID()"/>
</toolbarpalette>
or you can force the icon to display in nav bar against user will, this will take effect after each firefox restart, however not recommended
var navbar = document.getElementById("nav-bar");
var newset = navbar.currentSet;
if (newset.indexOf("MYBUTTON_ID") == -1)
{
if (newset.indexOf("reload-button,stop-button,") > -1)
newset = newset.replace("reload-button,stop-button,", "reload-button,stop-button,MYBUTTON_ID,");
else
newset = newset + ",MYBUTTON_ID";
navbar.currentSet = newset;
navbar.setAttribute("currentset", newset );
document.persist("nav-bar", "currentset");
}