I'm using jQuery templates for a website I developed and they work perfectly fine on Chrome, Safari, and even IE9, but the templates just won't render on Firefox. I'm loading them externally, and the $.get is processed (I've checked Firebug, the get goes through and pulls the right file), but then I'm greeted with a blank page and inspecting the html reveals the body element contains only the footer (included in the html), but with display : none, which is how it should be, so the javascript ran to completion (since the footer is hidden inside the loadtemplate functions). It seems that Firefox is simply skipping the $.tmpl() call. Here's the function :
var loadTemplate = function(templateName){
$.get(templateName, function(template){
$.tmpl(template).appendTo("body");
});
};
var loadHomePage = function(){
history = [];
clearPage();
loadTemplate("./templates/home.tmpl");
current_page = "./templates/home.tmpl";
}
var clearPage = function(){
$(".page-content").remove();
$(".page-header").remove();
$("#popup-container").remove();
$(".page-footer").hide();
};
Any help would be greatly appreciated, I can follow up with more code if required as well.
EDIT: even works on Opera, I don't need to support it so the styles don't work (using LESS which Opera doesn't support and a css file strictly for IE), but it still loads the templates without a problem.
Requesting a template may get processed as HTML by some browsers, which in-turn can result in a mangled template. Try setting the datatype to "text" so that all browsers properly return un-modified text.
$.get(templateName, function(template){
$.tmpl(template).appendTo("body");
}, "text");
Related
We have a problem that is only evident on iOS browsers (iOS 12.0) with our SPA application that uses HTML object tags to load widgets (HTML/CSS/JS files) through JavaScript onto the page.
The issue is an intermittent one when the page is loaded some of the widgets don't display/render on the screen, yet are loaded into the DOM and can be viewed/highlighted with full element properties in the Safari Web Inspector. but are “invisible” to their user. The problem will occur about 50% of the time if there are 4 widgets to load on a page, 2 typically won't display and it will be different widgets not displaying each time, with no detectable pattern.
The widget javascript load events run properly and there are no errors in the console. In the Safari Web Inspector, we can see some of the HTML elements from the non-rendering object are loaded at position 0,0 but their style is correct in the DOM (left and top set correctly, display: inline, etc.).
Here is the code that loads the widgets (the fragment is added to the DOM after all widgets are setup):
function loadWidget(myFrag, widgetName) {
var widgetObj = document.createElement("object");
widgetObj.data = "widgets/" + widgets[widgetName].type + ".html"; // location of widget
widgetObj.className = "widget unselectable";
widgetObj.id = widgetName;
widgetObj.name = widgetName;
myFrag.appendChild(widgetObj); // build widgets onto fragment
widgetObj.addEventListener("load", widgetLoaded, false); // Run rest of widget initialisation after widget is in DOM
widgetObj.addEventListener("error", badLoad, true);
}
Here is the code in the load event that configures the widget once loaded (we work around a Chrome bug that also affects Safari where the load event is fired twice for every object loaded):
function widgetLoaded(e) {
var loadObj = e.target;
if (loadObj === null) {
// CHROME BUG: Events fire multiple times and error out early if widget file is missing so not loaded (but this still fires), force timeout
return;
}
var widgetName = loadObj.id;
// CHROME BUG: Workaround here is to just set the style to absolute so that the event will fire a second time and exit, then second time around run the entire widgetLoaded
if ((parent.g.isChrome || parent.g.isSafari) && !widgets[widgetName].loaded) {
widgets[widgetName].loaded = true; // CHROME: WidgetLoaded will get run twice due to bug, exit early first time.
loadObj.setAttribute("style", "position:absolute"); // Force a fake style to get it to fire again (without loading all the other stuff) and run through second time around
return;
}
var defView = loadObj.contentDocument.defaultView; // Pointer to functions/objects inside widget DOM
loadObj.setAttribute("style", "position:absolute;overflow:scroll;left:" + myWidget.locX + "px;top:" + myWidget.locY + "px;z-index:" + zIndex);
loadObj.width = myWidget.scaleX * defView.options.settings.iniWidth; // Set the width and height of the widget <object> in dashboard DOM
loadObj.height = myWidget.scaleY * defView.options.settings.iniHeight;
}
The code performs correctly in Chrome (Mac/Windows), IE and Safari (Mac), however, presents the random invisible loading issue in iOS Safari and also in iOS Chrome.
Any ideas what causes this and what the workaround could be?
We couldn't find the exact source of this issue after a lot of investigation and are fairly sure this is a webkit bug. However there is an acceptable workaround, which is to replace the object tag with an iframe tag, and it looks to be working exactly the same way (replace .data with .src) with a bonus it doesn't exhibit the chrome bug where onload events are fired twice, so Chrome runs our app faster now.
Pretty new to jQuery here, I've got a chunk of code that works OK in Chrome, but fails in IE9 (have not tried FF yet).
Here's the code:
var textColor = $('#navmenu-body').css('color');
textColor = textColor.slice(4);
In IE9, I get an error to the effect that slice can't be called because textColor is undefined.
I was not sure if it's because jQuery just can't find the #navmenu-body element or that it can't find the CSS attribute color.
So I did:
var j = $('#navmenu-body');
var textColor = $('#navmenu-body').css('color');
textColor = textColor.slice(4);
In IE9's console, j.length returns 0. So the selector is indeed, not working
Here's the #navmenu-body HTML DOM
<div id="navmenu-body" class="x-panel-body x-panel-body-cssmenu x-layout-fit x-panel-body-cssmenu" style="height: 398px; left: 0px; top: 0px; width: 200px;">
</div>
Do I need to do something else for IE9 support ?
As per T.J. Crowder answer, I think I may have a problem where the selector is called before the element I'm trying to get is available.
I am primarily developing in Chrome (using ExtJS which dynamically generates all HTML content, so there may be some conflicts with jQuery) and I had to change:
$(document).ready(function () {
...
var textColor = $('#navmenu-body').css('color');
textColor = textColor.slice(4);
});
to:
$(window).load(function () {
...
var textColor = $('#navmenu-body').css('color');
textColor = textColor.slice(4);
});
For it to work in Chrome. But that "fix" doesn't work in IE9 apparently. From what I can read, it would seem ExtJS (which generates all of my HTML content) is initialized after the DOM and jQuery is ready, so that would explain it... By why would it work in Chrome then ?
I think I need to open a new, ExtJS related question.
var j = $('#navmenu-body');
var textColor = $('#navmenu-body').css('color');
textColor = textColor.slice(4);
So in IE9's debugger, turns out j is defined so it would seem jQuery has troubles getting the CSS attribute and textColor ends up being null.
No. The way jQuery works, $(...) will always return a jQuery object. That jQuery object may have no matching elements in it, but it won't be undefined or null.
But that object is apparently empty, because that's the only time jQuery will return undefined from css("color"). (Even if the first element in the set has no color, it will return "", not undefined.)
Do I need to do something else for IE9 support ?
No, all current versions of jQuery support IE9 directly.
What's going on here is that in your IE9 testing, the selector #navmenu-body didn't match any elements as of when you ran it. You'll have to determine why that is, as we don't have enough information in the question to answer that.
At a guess, it sounds like IE9 is firing some event or callback earlier than Chrome is (or you have a race condition and it was just luck of the draw). Or you're using conditional comments and that element just doesn't exist in IE9. (IE9 still had conditional comments.) Or an error occurred elsewhere in IE9, stopping your code and preventing your adding that element to the DOM. Etc. So look at where you're doing this code relative to where that element is created. Fundamentally, if the element exists and is in the DOM as of when you run var textColor = $("#navmenu-body").css("color");, textColor will be a string. It may be an empty string, but it'll be a string.
Re your edit about switching from ready to load: It sounds like whatever ExtJS stuff you're doing to create the element is happening after an ajax call or some such, and that call is completing before the load event fires on Chrome (so the element is there) but after load fires on IE9 (so it isn't).
Ideally, you want to register a callback with ExtJS, telling ExtJS to call you when the operation creating the element is complete. Then you don't need to use ready or load.
A very dirty workaround is to poll:
$(document).ready(function () {
// ...
init();
function init() {
var navmenuBody = $('#navmenu-body');
if (!navmenuBody[0]) { // **Very** dirty workaround
setTimeout(init, 50); // It wasn't there yet, so check back in 50ms
return;
}
var textColor = navmenuBody.css('color');
textColor = textColor.slice(4);
}
});
But again, that's a very dirty workaround. I'm sure there's a relevant callback you can get from ExtJS.
I came up to this problem where I have a set of links and I need to get the value of the selected one. I am using AJAX to acquire want I want. But is there another way? My current code is not working on other browsers and IOS devices. Anyway this is how it goes:
For example I have 2 dynamically generated links:
Link 1 (Value is Google)
Link 2 (Value is Yahoo)
Say I clicked Link 1. I need to get the value (in my case I used title="Google") of that link which is "Google" and pass that variable to a file_get_contents using variable $linkName. So it will look like:
file_get_contents("http://domain.com/link_contents/includes/**$linkName**")
file_get_contents("http://domain.com/link_contents/includes/**Google**")
I'm using CodeIgniter framework btw.
As of now, I have a working code and used AJAX. But, it's ONLY working with Chrome browser using: Desktop and Android devices. Sadly, it's not working on IOS devices. As far as I can remember, it was working few days ago with IOS but suddenly it's not. I'm in the process of researching on that too if my AJAX code has an effect to IOS devices.
Anyway. It was actually my first time to do AJAX so I apologize my code is quite messy. But this is how I did it:
On my header.php I have the ff:
$(document).ready(function(){
var getLink = $('.linkClass');
getLink.each(function(i){
$(this).click(function(){
var linkName = $(this).attr('title');
$.ajax({
url: 'http://domain.com/asset/file_get_contents.php',
type: "POST",
data: { getFromLinkClass: linkName }
}).done(function( result ) {
$('#divID').html(result);
});
});
});
});
On my domain.com/asset/file_get_contents.php file,
$linkName = $_POST["getFromLinkClass"];
if ($linkName != null) {
$links = file_get_contents("http://domain.com/link_contents/includes/$linkName", true); echo $links;
}
Lastly, on my index.php I can just call the html result which is
<div id="divID"></div>
As I said, this is working but in Chrome only: on Desktop and Android Chrome.
Any suggestions/ideas/comments? Or is there any other way to do this so that it will work on other browsers and IOS devices?
=======================
UPDATE:
I changed my script, disregarded my AJAX code and used pure Javascript instead. It's now working well with other browsers too.
$links = file_get_contents("http://domain.com/link_contents/includes/".$linkName, true);
echo $links;
Try This.. You must add http:// or https:// as protocol if you want to access external urls. Also concat $linkName after URL
I have a very basic html element that I would like to fadeIn(). I am however using require.js so I believe this could be part of the problem. I am using jQuery 2.0.3 When using fadeIn I get this error:
SecurityError: The operation is insecure.
chrome://firebug/content/console/commandLineExposed.js
Line 5
I have never seen this before, I have reset firefox and my PC.
Html
<message-box>
<message-info></message-info>
<close-box>x</close-box>
</message-box>
JS
$('message-Box').fadeIn();
I only get this error with firefox v27. No other browsers are having this problem, but I haven't tested it in any older versions of FF
I am not seeking help for anything other than the error...
See the error in action? and run this command: SD.message.showMessage('Somehow this breaks everything', 'bad');
-----Edit-------
So sadly you'll need to test this Here I assure you this is SFW, its just the sign in page.
I am confident there must be something in my other JS files that is conflicting, but I, as yet, have not found the problem.
I removed a fiddle that was here as it in no way helped the question, since adding the bounty I want it to be as helpful as possible.
Second Edit
Oddly, when running any show(), hide(), fadeIn() etc an iframe is created at the base of the page, just before the body. I'll need to have a think in my code why this would be happening.
Third Edit
I have no reason or explanation for this, but updating to jQuery 2.1.0 has fixed my issues. If anybody can explain the problem then I'd love to give them the points :)
Stepping through the jQuery code, you eventually hit this internal function below. The security error is thrown when jQuery attempts to write to the iframe document. jQuery 2.1.0 has a different way of determining the default node display value so you can just treat this as a jQuery/browser combo bug. You can minimally recreate the security error by pasting the following into the console:
var iframe = jQuery("<iframe frameborder='0' width='0' height='0'/>").css( "cssText", "display:block !important" ).appendTo(document.documentElement);
iframe[0].contentWindow.document.write("<!doctype html><html><body>");
Internal jQuery function:
function css_defaultDisplay( nodeName ) {
var doc = document,
display = elemdisplay[ nodeName ];
if ( !display ) {
display = actualDisplay( nodeName, doc );
// If the simple way fails, read from inside an iframe
if ( display === "none" || !display ) {
// Use the already-created iframe if possible
iframe = ( iframe ||
jQuery("<iframe frameborder='0' width='0' height='0'/>")
.css( "cssText", "display:block !important" )
).appendTo( doc.documentElement );
// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;
doc.write("<!doctype html><html><body>");
doc.close();
display = actualDisplay( nodeName, doc );
iframe.detach();
}
// Store the correct default display
elemdisplay[ nodeName ] = display;
}
return display;
}
As per specification custom elements shall have '-' in their tags, so your markup should look like this:
<message-box>
<x-message><div></div></x-message>
<x-close>x</x-close>
</message-box>
After the change and corresponding style updates it works as far as I can tell: http://jsfiddle.net/9Frn8/11/
Looks like this may be due to the absolute paths in your CSS file. I also see (in console) you are trying to do a call to localhost (which fails, of course). There seems to be some issues in your code that is causing Firefox to stop specific processes. Specifically, something that firefox considers cross-domain.
This is most likely a Same-Origin-Policy issue.
It seems this is a known problem and has been asked several times before here in SO however I do not see anything specific to jQTouch so I thought I would give it a try.
jQT will dynamically load pages when a link is clicked. In this page I would like to include something like
<script>
$.include('javascriptfile.js', function() {alert('do something with results of this file to an already existing div element');};
</script>
The $.include is a jquery plugin I found that mimics the $.load with a few more smarts added to it. Tested to work on FF but not in Chrome or most importantly, Safari.
The alert is never displayed. FireBug never shows the javascript even being loaded. If I put an alert before the $.include I still do not see anything.
I have tried an onclick/ontap event that would then run this code that was included in the head tag, no luck.
Edit: I am using the r148 revision of jQT. This was working prior to moving to this version, i believe.
Did you try to add the javascript file using one of these two methods:
Static Way:
<script type="text/javascript">
function staticLoadScript(url){
document.write('<script src="', url, '" type="text/JavaScript"><\/script>');
}
staticLoadScript("javascriptfile.js");
modifyDivFn(processFnInFile());
</script>
Dynamic way:
<script type="text/javascript">
function dhtmlLoadScript(url){
var e = document.createElement("script");
e.src = url;
e.type="text/javascript";
document.getElementsByTagName("head")[0].appendChild(e);
}
onload = function(){
dhtmlLoadScript("javascriptfile.js");
modifyDivFn(processFnInFile());
}
</script>
After the include you can call a function that does the processing you want (that being processFnInFile()) which result will be passed to modifyDivFn (and modify the div you want.) You could do this in one function, just to illustrate the idea.
Source: Dynamically Loading Javascript Files
Well Geries, I appreciate your help but ultimately the answer required a drastic rethinking of how I was using JQTouch. The solution was to move everything to an onclick event and make all the hrefs link to #. This might be what you were talking about Geries.
In the onclick function I do the logic, preloading, loading of the page through my own GET through jquery, then use the public object jQT.goTo(div, transition). This seems to get around the WebKit bugs or whatever I was running into and this now owrks on FireFox, Chrome, Safari, iPhone, and the lot.
I do run into a few animation issues with JQT but I think these are known issues that I hope Stark and the gang at JQTouch are working on.