JavaScript Behavior difference: IE11/Edge vrs Chrome/Firefox - javascript

function displayInfo(nKey) {
var i, xdata, xfilm, xprop;
if(!nKey) return false;
var objFilm;
var imgRef;
//iterate through all object properties; display their attributes
var jqxhr = $.getJSON('dbMovies.json', function(data) {
$.each(data.disc, function(i, xdata) {
if(xdata.key == nKey) {
objFilm = xdata.film;
imgRef = xdata.img;
if(xdata.doc) bkDoc = true;
return false;
}
}); // $.each
})
.done(function() {
// objFilm has either a single film object or else an array of film objects
var arInfo = [];
if(!$.isArray(objFilm)) {
var arProps = Object.keys(objFilm);....//absolutely
arProps.forEach(function(item) {
if(item != "ref") {
arInfo.push(item + ": " + objFilm[item] + "<br>");
} else {
arInfo.push(item + ": <a href=" + objFilm[item] + " target=_blank>Wikipedia</a>");
}
});
var w = window.open('', '', 'width = 650, height = 500, resizable');
$(w.document.body).html(arInfo.join(""));
}) // .done
I have what we'll call a kiosk app that contains the contents of my film library as stored in a JSON file. One can access the contents in several ways, but each yields a display of all relevant titles. For example, searching for films with Sophia Loren, one would see this result:
All browsers work to this point.
You can see that each film has a link that leads to certain information about the film.
Although one browser (Mac Safari) reportedly does not display the Wikipedia link, all other browsers do. But only the Microsoft browsers (Edge, IE11) show the associated thumbnail. Therefore(?), only the Microsoft browsers respond to a click by invoking my display engine on the full version of the image. All browsers respond well and equally on more direct invocations of the display engine. For example, see [http://www.michaelbroschat.com/LongviewChristmas/LongviewChristmas.html].
The information window is created dynamically upon clicking the index number link shown in the first illustration.
All browsers successfully create the new window and most of the information data items. In fact, Chrome and Firefox appear to create the image display code but don't act upon it.
The entire app can be seen at http://www.michaelbroschat.com/film/disccatalog.html
I would love to know why Chrome and Firefox don't allow what the Microsoft browsers allow.

You left out of your question a critical part of the code, that being the code that creates the <a> tag around the image reference.
The problem you're having is that you're stuffing the assembled HTML for the list of films into that popup window, which is opened with no URL reference. Your <img> tags are built with relative URLs (like "liners/i0001.jpg"), but since there's no base URL for the browser to reference the image can't be loaded.
Internet Explorer may be making some inference that the popup window has the same base URL as the parent, but other browsers apparently don't do that.

I have some theories on this portion of your code:
............arProps.forEach(function(item) {
................if(item != "ref") {
....................arInfo.push(item + ": " + objFilm[item] + "<br>");
................} else {
....................arInfo.push(item + ": <a href=" + objFilm[item] + " target=_blank>Wikipedia</a>");
................}
............});
ONE: Be sure the anchor tag is using single quotes or double quotes depending on your preference when you output the source such as:
Wikipedia
My guess is that being only your version of safari is having an issue with the Wikipedia link it is sensitive to the quotes.
As far as the image goes, where is the img tag to output an image path?

Related

Apply Masonry on content from Facebook API

I have been trying to implement Masonry into this project for ages now, and I would be totally happy to have someone who can help me out. The internet is full of similar problems with masonry, but none of the given solutions could help me fix this.
Basically, I am pulling reviews from my Facebook page via the Open Graph API with the following code. The Facebook response data is converted from json to an array and then stored in the fb_reviews variable for later use. This one works as desired:
[...]
function (response) {
if (response && !response.error) {
//convert to array
fb_reviews = Object.keys(response).map(function (_) {
return response[_];
});
//only store needed data of fb_reviews[0]
fb_reviews = fb_reviews[0];
reviews();
}
;
});
[...]
This works perfectly. As you can see, the following reviews() function is called next to display the Facebook data, and this is where I would like masonry to kick in:
// DISPLAY REVIEWS
var print2 = "";
var reviews = function() {
var z = fb_reviews.length - 1;
var print2 = "";
for (i = 0; i < z; i++) {
//put together div container for every review object
print2 += '<div class="review" id="review-' + i + '"><div class="meta">' + fb_reviews[i].reviewer.name + ' rated ' + fb_reviews[i].rating + '/5</div><blockquote>' + fb_reviews[i].review_text + '</blockquote></div>';
}
print2 = $(print2);
// still works!!!
$("#reviews").append(print2);
//until here, everything still works, but the following does no longer work:
$("#reviews").masonry({
itemSelector: '.review'
});
}
;
The content is appended as desired etc., but I have literally tried any possible way to initialize masonry, including using all snippets I could find for appended content, e. g.:
$("#reviews").append( print2).masonry( 'appended', print2 );
There are many more, including reload and layout etc, but this does not make much sense to me, because there is no content in the #reviews-div-container until all Facebook reviews are loaded and appended.
Masonry ALWAYS seems to be called BEFORE the Facebook reviews are appended, no matter where I would position and spread the masonry code snippets.
So what is the best way to get Masonry initialized AFTER the Facebook data is stored and appended?
Thank you so much in advance for your help! Really appreciate your support
Simon

ReportViewer Web Form causes page to hang

I was asked to take a look at what should be a simple problem with one of our web pages for a small dashboard web app. This app just shows some basic state info for underlying backend apps which I work heavily on. The issues is as follows:
On a page where a user can input parameters and request to view a report with the given user input, a button invokes a JS function which opens a new page in the browser to show the rendered report. The code looks like this:
$('#btnShowReport').click(function () {
document.getElementById("Error").innerHTML = "";
var exists = CheckSession();
if (exists) {
window.open('<%=Url.Content("~/Reports/Launch.aspx?Report=Short&Area=1") %>');
}
});
The page that is then opened has the following code which is called from Page_Load:
rptViewer.ProcessingMode = ProcessingMode.Remote
rptViewer.AsyncRendering = True
rptViewer.ServerReport.Timeout = CInt(WebConfigurationManager.AppSettings("ReportTimeout")) * 60000
rptViewer.ServerReport.ReportServerUrl = New Uri(My.Settings.ReportURL)
rptViewer.ServerReport.ReportPath = "/" & My.Settings.ReportPath & "/" & Request("Report")
'Set the report to use the credentials from web.config
rptViewer.ServerReport.ReportServerCredentials = New SQLReportCredentials(My.Settings.ReportServerUser, My.Settings.ReportServerPassword, My.Settings.ReportServerDomain)
Dim myCredentials As New Microsoft.Reporting.WebForms.DataSourceCredentials
myCredentials.Name = My.Settings.ReportDataSource
myCredentials.UserId = My.Settings.DatabaseUser
myCredentials.Password = My.Settings.DatabasePassword
rptViewer.ServerReport.SetDataSourceCredentials(New Microsoft.Reporting.WebForms.DataSourceCredentials(0) {myCredentials})
rptViewer.ServerReport.SetParameters(parameters)
rptViewer.ServerReport.Refresh()
I have omitted some code which builds up the parameters for the report, but I doubt any of that is relevant.
The problem is that, when the user clicks the show report button, and this new page opens up, depending on the types of parameters they use the report could take quite some time to render, and in the mean time, the original page becomes completely unresponsive. The moment the report page actually renders, the main page begins functioning again. Where should I start (google keywords, ReportViewer properties, etc) if I want to fix this behavior such that the other page can load asynchronously without affecting the main page?
Edit -
I tried doing the follow, which was in a linked answer in a comment here:
$.ajax({
context: document.body,
async: true, //NOTE THIS
success: function () {
window.open(Address);
}
});
this replaced the window.open call. This seems to work, but when I check out the documentation, trying to understand what this is doing I found this:
The .context property was deprecated in jQuery 1.10 and is only maintained to the extent needed for supporting .live() in the jQuery Migrate plugin. It may be removed without notice in a future version.
I removed the context property entirely and it didnt seem to affect the code at all... Is it ok to use this ajax call in this way to open up the other window, or is there a better approach?
Using a timeout should open the window without blocking your main page
$('#btnShowReport').click(function () {
document.getElementById("Error").innerHTML = "";
var exists = CheckSession();
if (exists) {
setTimeout(function() {
window.open('<%=Url.Content("~/Reports/Launch.aspx?Report=Short&Area=1") %>');
}, 0);
}
});
This is a long shot, but have you tried opening the window with a blank URL first, and subsequently changing the location?
$("#btnShowReport").click(function(){
If (CheckSession()) {
var pop = window.open ('', 'showReport');
pop = window.open ('<%=Url.Content("~/Reports/Launch.aspx?Report=Short&Area=1") %>', 'showReport');
}
})
use
`$('#btnShowReport').click(function () {
document.getElementById("Error").innerHTML = "";
var exists = CheckSession();
if (exists) {
window.location.href='<%=Url.Content("~/Reports/Launch.aspx?Report=Short&Area=1") %>';
}
});`
it will work.

Can you control which display a window created by Javascript is displayed on?

My PC has more than one display attached. I'm working on a web app that displays data in a table in the browser. When the user clicks on a row of the table, a window with details about the row selected is displayed. If the user clicks on a different row, a new window opens.
I have two requirements I need to make work:
The windows should not stack up one on top of the other, they should cascade. I've got code that works for Firefox, but IE and Chrome just open each window in the same place so they stack up. If I keep track of the number of windows opened, I can finagle a cascading mechanism, but is there a better way?
If the machine has multiple displays, it'd be nice if the window with the table were on one screen and the details windows opened on the other. I haven't been able to find anything in any of the searches I've done. Is there some code somewhere that does this?
Edit:
For #Neal:
Function newWin( mypage, myname, cascade ) {
if (!cascade) cascade = false;
if (!myname)
myname = 'DETAILS';
var w = 820;
var h = 685;
var settings = 'height=' + h + ',';
settings += 'width=' + w + ',';
if (!cascade) {
if (screen.width) {
var winl = (screen.width - w) / 2;
var wint = (screen.height - h) / 2;
}
else {
winl = 0;
wint = 0;
}
if (winl < 0) winl = 0;
if (wint < 0) wint = 0;
settings += 'top=' + wint + ',';
settings += 'left=' + winl + ',';
}
settings += 'scrollbars=yes,resizable=yes,menubar=yes,location=yes';
gPopupWindow = window.open(mypage, myname, settings);
// fix for IE focus
// when from ajax loaded list
// see convoy dropdownlist item click
//gPopupWindow.focus();
setTimeout(function () { gPopupWindow.focus() }, 0);
}
By passing true for cascade, Firefox lets the OS open the window where it wants. But IE & Chrome always put the window in the same place, though where it goes on the screen is different for each browser. I was hoping that IE & Chrome would act like Firefox does, but browser differences is a fact of life.
As I said, I can keep track of how many windows have been opened by calling this function and compute new left & top coordinates based on that number. I'd rather not, though.
The fact is that there's no way to control on which screen a new window will be displayed on a multi-screen system from JavaScript. Not without writing your own DLL and incorporating it into your application. There are ways to call functions in DLLs, but it's not worth it, as the DLL would be Windows specific and you'd need to do something else on the Mac & Linux.
Further, different browsers complicate this problem, as the method to add custom code differs from browser to browser, as well.
For that matter, if you don't specify the left & top coordinates when displaying a new window, each browser displays the new window in a different place on whatever screen it decides to display the window on. The behavior is completely inconsistent browser to browser, let alone OS to OS.
Don't do it.

Opening a new window/ document in PhoneGap

With the following code, I am able to open a new window on a Desktop browser:
var thisWin = window;
var oauthWin = thisWin.open(data, 'twitter-oauth-window', 'location=0,status=0,width=800,height=400');
var lastUrl = oauthWin.location.href;
var meh = true;
var oauthInt = thisWin.setInterval(
function()
{
if (meh)
{
alert(
'\noauthWin.closed: ' + oauthWin.closed +
'\noauthWin.location: ' + oauthWin.location +
'\nthisWin.closed: ' + thisWin.closed +
'\nthisWin.location: ' + thisWin.location +
'\noauthWin===thisWin: ' + (oauthWin === thisWin));
meh = false;
}
// do more stuff here
}
);
In the debug output within the alert:
oauthWin===thisWin: false
Which is what it should be. However, when the same code is run within PhoneGap, I get the following:
oauthWin===thisWin: true
Which indicates that PhoneGap has opened the new URL in the same window, replacing the current HTML document.
I wish to open the new URL separately, and to be able to close it upon a certain condition being met, and revert to the old one.
Can this be achieved in PhoneGap, and how?
Thanks!
Now with PhoneGap 2.3+, I was unable to get URLs to open in Mobile Safari in any way. Using _blank didn't work, and I tried window.open(url, '_blank'), but this now opens the URL using the InAppBrowser plugin (which pretty much sucks). I thought it was interesting that that one used a plugin though, so I decided to write a plugin to open URLs using the standard method of opening URLs in iOS apps. You can see/grab the code on this gist here: https://gist.github.com/typeoneerror/5097118.
It's simple enough. In my example, I wired up links that have a class called "_blank" with jQuery and opened those URLs with the plugin call:
// execute the plugin called OpenUrl, signature:
// exec(successCallback, errorCallback, pluginName, pluginMethod, params)
cordova.exec(success, error, "OpenUrl", "openUrl", [url]);
I'm sure you could rewrite the plugin easily for each platform you require it on. This one is iOS-specific.

How to tell if an image has loaded correctly

Is there a way to tell, after the fact, whether an image (placed with the <img> tag, not via JS) has loaded correctly into a page? I have a gallery of head shots, and occasionally the third-party image server ends up serving up a 404. I can change the server-side code to use an onerror="showGenericHeadshot()", but I really want to avoid making changes to server-side code. Ultimately, I want to determine if an image is missing or broken and replace it with a generic "Image Not Found" graphic. Things I've tried:
Image.prototype.onerror = showGenericHeadshot -- doesn't work for <img> tags
$('img[src*=thirdpartyserver.com]).error(showGenericHeadshot) -- doesn't work in IE
$('img[src*=thirdpartyserver.com]).css('backgroundImage','url(replacementimage.gif)') -- works, but still doesn't get rid of the broken image icon in IE
<img scr='someUrl' id="testImage" />
jQuery('#testImage').bind('load',function(){
alert ('iamge loaded');
});
to avoid race condition do as below
<img _src="http://www.caregiving.org/intcaregiving/flags/UK.gif" />
// i have added an underscore character before src
jQuery('img').each(function(){
var _elm=jQuery(this);
_elm.bind('load',_imageLoaded).attr('src',_elm.attr('_src'))
});
function _imageLoaded()
{
alert('img loaded');
}
Unfortunately, I'm not able to accept either #TJ Crowder's nor #Praveen's excellent answers, though both do perform the desired image-replacement. #Praveen's answer would require a change to the HTML (in which case I should just hook into the <img> tag's own error="" event attribute. And judging by network activity, it look like if you try to create a new image using the url of an image that just 404ed in the same page, the request actually does get sent a second time. Part of the reason the image server is failing is, at least partly, our traffic; so I really have to do everything I can to keep requests down or the problem will only get worse..
The SO question referred to in #danp's comment to my question actually had the answer for me, though it was not the accepted answer there. I'm able to confirm that it works with IE 7 & 8, FF and webkit browsers. I'm doubtful it will work with older browsers, so I've got a try/catch in there to handle any exceptions. The worse case will be that no image-replacement happens, which is no different from what happens now without doing anything. The implementation I'm using is below:
$(function() {
$('img[src*=images.3rdparty.com]').each(
function() {
try {
if (!this.complete || (!$.browser.msie && (typeof this.naturalWidth == "undefined" || this.naturalWidth == 0))) {
this.src = 'http://myserver.com/images/no_photo.gif';
}
} catch(e) {}
}
);
});
Would an alternate text be sufficient? If so you can use the alt attribute of the img tag.
I think I've got it: When the DOM is loaded (or even on the window.load event — after all, you want to do this when all images are as complete as they're going to get), you can retroactively check that the images are okay by creating one new img element, hooking its load and error events, and then cycling through grabbing the src from each of your headshots. Something like the code below (live example). That code was just dashed off, it's not production quality — for instance, you'll probably want a timeout after which if you haven't received either load or error, you assume error. (You'll probably have to replace your checker image to handle that reliably.)
This technique assumes that reusing a src does not reload the image, which I think is a fairly reliable assumption (it is certainly an easily testable one) because this technique has been used for precaching images forever.
I've tested the below on Chrome, Firefox, and Opera for Linux as well as IE6 (yes, really) and IE8 for Windows. Worked a treat.
jQuery(function($) {
var imgs, checker, index, start;
// Obviously, adjust this selector to match just your headshots
imgs = $('img');
if (imgs.length > 0) {
// Create the checker, hide it, and append it
checker = $("<img>").hide().appendTo(document.body);
// Hook it up
checker.load(imageLoaded).error(imageFailed);
// Start our loop
index = 0;
display("Verifying");
start = now();
verify();
}
function now() {
return +new Date();
}
function verify() {
if (!imgs || index >= imgs.length) {
display("Done verifying, total time = " + (now() - start) + "ms");
checker.remove();
checker = undefined;
return;
}
checker[0].src = imgs[index].src;
}
function imageLoaded() {
display("Image " + index + " loaded successfully");
++index;
verify();
}
function imageFailed() {
display("Image " + index + " failed");
++index;
verify();
}
function display(msg) {
$("<p>" + now() + ": " + msg + "</p>").appendTo(document.body);
}
});​
Live example

Categories

Resources