Image Map links not firing in a jQuery UI dialog (IE only) - image

I'm attempting to place an image map into a jQuery UI dialog. Initially, the and are hidden on the page so that I don't have to do any AJAX. When the dialog is triggered, the and are placed in the dialog and the hidden original content has its link to the image map removed.
There are a few links on the image map in tags and in Firefox, Chrome etc the links are positioned correctly and work.
However, in all versions of IE (the web site is SharePoint 2007 and compatibility mode is on), the links do not fire on the image map. You can hover over the rectangles and be shown the link, but the action never fires.
Code used to initialise below:
$(document).ready(function() {
$('.processDiagram').click(function() {
var phase = $(this).attr('title');
var text = $('#'+phase+' div').html();
var mapname = $('#'+phase+' map').attr('name');
$('#'+phase+' map').attr('name', ''); // null out the background map name so it doesn't get confused
var $dialog = $('<p></p>').html(text).dialog({modal:true, autoOpen:false, width:620, title:phase, beforeClose: function(event, ui) { $('#'+phase+' map').attr('name', mapname); }});
$dialog.dialog('open');
return false; // So firefox won't just follow the link
}
}
I could really do with some help here as I have no idea why the links aren't firing.
Thanks,
Steve

So, the reason is the layout being position:relative does a number on IE, moving all of the hotspots to be relative to the body and not to the image map itself.
Solution is to fix that layout issue.

Related

Scrolling to elements in CKEditor via JavaScript

My CKEditor fields often contain lots of content with h1, h2, h3, etc headings, and I've written a script that presents all the headings in a sidebar for quick reference. I'd also like to use this sidebar as a navigation menu for the editor content, so clicking a heading in the sidebar scrolls the editor to the related heading, but I can't figure out how to wire it all up.
This post at https://davidwalsh.name/scroll-element-ckeditor leads me to believe that it should be possible, but I can't figure out how to get to the "editor" element described in the post.
My sidebar is built with jQuery from a CKEditor textarea with id="content" like this...
var content = $('<div/>').append($('#content').val());
var sidebar = "";
$(content).find('h1,h2,h3,h4,h5,h6').addClass('heading');
$(content).find('.heading').each(function () {
sidebar += this.outerHTML;
});
$('#sidebar').html(sidebar);
I imagine using jQuery :contains() to identify heading elements in the editor based on the text they contain, but I can't figure out how to hook back into the CKEditor instance in a way that enables this kind of DOM activity.
I am using CKEditor 4 but am happy to upgrade to version 5 if it offers a better solution to my problem.
Thanks!
This is what wound up working for me:
var content = $('<div/>').append($('#content').val());
var sidebar = "";
$(content).find('h1,h2,h3,h4,h5,h6').addClass('heading');
$(content).find('.heading').each(function () {
sidebar += this.outerHTML;
});
$('#sidebar').html(sidebar);
$('#sidebar .heading').click(function() {
var element = $('#cke_content iframe').contents().find(':contains(' + $(this).text() + ')')[2];
if (element) {
element.scrollIntoView();
}
});

onload event for snap svg image not firing in Internet Explorer or Safari

I am trying to dynamically load images in Snap.svg and then once the image has loaded do some processing to it. The load event is firing in Chrome, Firefox and Opera but is does not fire in Internet Explorer or Safari.
I have this setup in Plunker
var s = null;
var g = null;
var image = null;
//$(document).ready(function($) {
$(window).load(function() {
s = Snap("#svgout");
g = s.g();
$("#baseimage").attr("src", "http://www.customcribboards.com/resources/svgs/preview/29.png");
$("#baseimage").on("load", function() {
console.log("hidden image loaded");
image = g.image($(this).attr("src"), 0,0, 400,400);
image.node.onload = function () {
console.log("svg image loaded 1");
};
$(image.node).on("load", function() {
console.log("svg image loaded 2");
});
});
});
Any ideas how to make the onload event fire on an svg image load in Internet Explorer and Safari?
For a pure SVG document (SVG being the root element), I have found the following.
In IE9+ (IE11, Edge), putting an onload= in the root element doesn't seem to be respected per the spec or expectation. Instead, IE seems to fire the event "right away" i.e. after the opening of the root element is received, but before the DOM is fully loaded. So, your Javascript cannot find elements you'd expect to be there for example. I have experimented with delays etc. but that's a hokey kludge.
In Firefox, onload= in the root element works as expected, when the DOM is complete, the onload fires.
A workaround for IE is to omit the onload= in the root tag, but put one in a child element that is "late" or "last." This seems to defer firing onload= until the DOM is fully loaded. This kludge is not respected in Firefox, and actually seems to maybe break the triggered Javascript, in at least my case.
So the FF and IE approaches are divergent and seem mutually exclusive.

Creating image with hyperlink using google-apps-script

I have been trying to put an image with a hyperlink on it into a google apps script ui. I first thought of using createAnchor(), but that only allows text. Then I thought of using a button, but as far as I know you cannot open a new tab/window and redirect in a callback function.
I also tried createHTML(), but the element is not handled by it as yet.
I have seen people overlay transparent buttons over images, but still have same issue in callback.
My research has not found an answer to this. Does anyone have any solutions/examples?
Thanks
This worked for me on Chrome20 and IE9
// Container for box and results
var imageContainer = app.createFlexTable();
// Setup the button
var button = app.createButton("ImageButton");
button.setStyleAttribute("background", "url(dontshowimagehere.JPG) no-repeat");
button.setStyleAttribute("position", "absolute");
button.setStyleAttribute("color", "transparent");
button.setStyleAttribute('zIndex','1');
button.setStyleAttribute("border", "0px solid black");
imageContainer.setWidget(0, 0, button);
// image to click
var image = app.createImage("image.jpg").setId(imageId);
imageContainer.setWidget(1,0, image);
The image has a slight (3px) offset. If important, this looks to fix it http://www.w3schools.com/css/css_positioning.asp (use relative for the flex table and top etc for the image and button)
Did you try a transparent Anchor overlaying the image?
function doGet() {
var app = UiApp.createApplication().setTitle("Image Anchor");
var panel = app.createAbsolutePanel().setWidth('50%').setHeight('50%');
var image = app.createImage().setUrl("https://lh6.googleusercontent.com/-v0Q3gPQz03Q/T_y5gcVw7LI/AAAAAAAAAF8/ol9uup7Xm2g/s512/GooglePlus-512-Red.png").setStyleAttribute("width", "28px").setStyleAttribute("height", "28px");
var anchor = app.createAnchor("?", "https://plus.google.com/u/1/116085534841818923812/posts").setHeight("28px").setWidth("28px").setStyleAttribute("opacity", "0.1").setTarget("blank");
panel.add(image,100,50);
panel.add(anchor,100,50);
app.add(panel);
return app.close();
}
app.createAbsolutePanel()
.add(app.createImage('https://www.google.com/images/logos/google_logo_41.png'))
.add(app.createAnchor('','https://www.google.co.uk/intl/en/about/')
.setStyleAttributes({position:'absolute',top:'0px',left:'0px',width:'201px',height:'47px',opacity:'0'}))
This is a tested one. It works fine.
It doesn't work with positioning the image (as 'absolute').
It doesn't work with .setHorizontalAlignment(UiApp.HorizontalAlignment.CENTER)
I don't believe this is possible with the widgets available. I would suggest altering your UI's design to utilize an Anchor widget instead.
Use HTML Box if you are coding directly on your page. Click "Edit" to edit your page and go to "Insert>HTML Box" in your menu. It will accept javascript too! There are a few caveats - when using javascript, HTML Box will not accept links...too bad, but too many exploits there.
If you are coding in apps script, you could try to place the image on a panel and use absolute panel and position your link over your image. Another method could be to use the .setStyleAttribute for CSS styling and utilize the zIndex parameter to place a panel over top of your image....like so:
var panel = app.createSimplePanel();
// add your image to the simple panel or whatever panel you wish to choose in your GUI
var popPanel = app.createSimplePanel()
.setStyleAttribute('top','Y')
.setStyleAttribute('left','X')
.setStyleAttribute('zIndex','1')
.setStyleAttribute('position','fixed');
// add your anchor to the popPanel
app.add(panel).add(popPanel);
Not 100% sure if you can make this panel transparent, but you could try something like:
.setStyleAttribute('background',transparent')
or change the opacity via:
.setStyleAttribute('opacity','.5')
Hopes this gives you a few ideas!
I managed to do it with a single Anchor object and using CSS3.
It works on Chrome, I did not test it in other Browsers.
gui.createAnchor("", false, "$DESTINATION_URL$")
.setStyleAttributes({ "display":"block",
"width":"$IMAGE_WIDTH_IN_PIXEL$",
"height":"$IMAGE_HEIGHT_IN_PIXEL$",
"background":"url($URL_OF_THE_IMAGE$)",
"background-size":"100% 100%",
"background-repeat":"no-repeat" })
Of course you have to replace the $......$ with your data.
Thierry
If you first create all your HTML in a string, you can then replace the content of a page with the HTML you want like this:
var myString = 'the html you want to add, for example you image link and button';
var page = SitesApp.getSite('example.com', 'mysite').getChildByName('targetpage');
var upage = page.setHtmlContent('<div>' + myString + '</div>');

jQuery Functions need to run again after ajax is complete

I am developing a website that parses rss feeds and displays them based on category. You can view it here: http://vitaminjdesign.com/adrian
I am using tabs to display each category. The tabs use ajax to display a new set of feeds when they are clicked.
I am also using two other scripts- One called equalheights, which re-sizes all of the heights to that of the tallest item. And the other script I am using is called smart columns, which basically resize your columns so it always fills the screen.
The first problem I am having is when you click a new tab (to display feeds within that category). When a new tab is clicked, the console shows a jQuery error:
$(".block").equalHeights is not a function
[Break On This Error] $(".block").equalHeights();
The main problem is that each feed box fills up the entire screen's width (after you click on a tab), even if there are multiple feed boxes in that category.
MY GUESS - although all of the feeds (across all tabs) are loaded on pageload, when a new tab is selected, both jQuery scripts need to be run again. any ideas on how I can make this work properly?
One thing to note - I used the ajaxSuccess method for making equalHeights work on the first page...but it wont work after a tab is clicked.
My jQuery code for the tabs are below:
$(".tab_content").hide(); //Hide all content
$("ul.tabs li:first").addClass("active").show(); //Activate first tab
$(".tab_content:first").show(); //Show first tab content
$("#cities li:nth-child(1)").addClass('zebra');
$("#column li ul li:nth-child(6)").addClass('zebra1');
//On Click Event
$("ul.tabs li").click(function() {
$("ul.tabs li").removeClass("active"); //Remove any "active" class
$(this).addClass("active"); //Add "active" class to selected tab
$(".tab_content").hide(); //Hide all tab content
var activeTab = $(this).find("a").attr("href"); //Find the href attribute value to identify the active tab + content
$(activeTab).fadeIn(); //Fade in the active ID content
$(".block").equalHeights();
return false;
});
Thanks to Macy (see answer below), I have brought my jQuery script to the following: (still does not work)
$(document).ajaxSuccess(function(){
var script = document.createElement('script');
script.src = 'js/equalHeight.js';
document.body.appendChild(script);
equalHeight($(".block"));
I found some small problems in your code. I am not sure that my suggestions will solve all the problems, but I decide to describe my first results here.
1) You should remove comma before the '}'. Currently the call look like $("#column").sortable({/**/,});
2) The function equalHeight is not jQuery plugin. It is the reason why the call $(".block").equalHeights(); inside your 'click' event handler follows to the error "$(".block").equalHeights is not a function" which you described. You should change the place of the code to equalHeight($(".block")); like you use it on other places.
3) The script http://vitaminjdesign.com/adrian/js/equalHeight.js defines the function equalHeight only and not start any actions. Once be loaded it stay on the page. So you should not load it at the end of every ajax request. So I suggest to reduce the script
$(document).ajaxSuccess(function(){
var script = document.createElement('script');
script.src = 'http://vitaminjdesign.com/adrian/js/equalHeight.js';
document.body.appendChild(script);
equalHeight($(".block"));
$("a[href^='http:']:not([href*='" + window.location.host + "'])").each(function() {
$(this).attr("target", "_blank");
});
});
to
$(document).ajaxSuccess(function(){
equalHeight($(".block"));
$("a[href^='http:']:not([href*='" + window.location.host + "'])").each(function() {
$(this).attr("target", "_blank");
});
});
4) I suggest to change the code of http://vitaminjdesign.com/adrian/js/equalHeight.js from
function equalHeight(group) {
tallest = 0;
group.each(function() {
thisHeight = $(this).height();
if(thisHeight > tallest) {
tallest = thisHeight;
}
});
group.height(tallest);
}
to
function equalHeight(group) {
var tallest = 0;
group.each(function() {
var thisHeight = $(this).height();
if(thisHeight > tallest) {
tallest = thisHeight;
}
});
group.height(tallest);
}
to eliminate the usage of global variables tallest and thisHeight. I recommend you to use JSLint to verify all your JavaScript codes. I find it very helpful.
5) I recommend you to use any XHTML validator to find some small but sometime very important errors in the markup. Try this for example to see some errors. The more you follow the XHTML standards the more is the probability to have the same results of the page in different web browsers. By the way, you can dramatically reduce the number of the errors in your current code if the scripts included in the page will be in the following form
<script type="text/javascript">
//<![CDATA[
/* here is the JavaScript code */
//]]>
</script>
I didn't analysed the full code but I hope that my suggestions will solve at least some of problems which you described in your question.
Essentially, when you add a new element to the document, the equalheights script has not attached its behavior to that new element. So, the "quick fix", is probably to re-embed the equalheights script after an ajax request has completed so that it re-attaches itself to all elements on the page, including the elements you just added.
Before this line: $(".block").equalHeights(); , add a line of script which re-embeds/re-runs your equalheights script.
$.getScript('<the location of your equalHeightsScript>');
$.getScript('<the location of your smartColumnsScript>');
$(".block").equalHeights();
or
var script = document.createElement('script');
script.src = '<the location of your script>';
document.body.appendChild(script);
A better solution would be to upgrade the plugin so it takes advantage of live. However, I'm not up to that at the moment :)
Some Error Here
$("ul.tabs li").click(function() {
$("ul.tabs li").removeClass("active"); //Remove any "active" class
$(this).addClass("active"); //Add "active" class to selected tab
$(".tab_content").hide(); //Hide all tab content
.
.
.
});
Should be re-written like this
$("ul.tabs li").click(function() {
$(this).addClass("active").Siblings("li").removeClass("active");; //Remove any "active" class Add "active" class to selected tab
$(".tab_content").hide(); //Hide all tab content
.
.
.
});
I don't think you need to run the scripts again after the ajax, or at least that's not the "main" problem.
You seem to have some problems in the script smartColumn.js
Right now it seems to only operate on the ul with the id "column" ('#column'), and it is working on the one UL#column you do have, but of course your HTML has many other "columns" all of which have the class "column" ('.column') that you want it to work on as well.
Just to get the beginning of what you are trying to do, change all the selectors in smartColumn.js that say 'ul#column' to say 'ul.column' instead, and then alter the HTML so that the first "column" has a class="column" rather than an id="column".
That should solve the 100% wide columns at least.
That should solve your "Main" Problem. But there are other problems.

Safari - updating a link's title via XMLHTTPRequest on mouse hover?

I'm doing some Mac development in a WebView. I want to expand URLs that have been shortened by a url shortener, and display that expanded URL to the user. So, given a link whose src attribute is set to http://is.gd/xizMsr, when the user hovers over the link I want the title tooltip to display http://google.com
My link tag looks like this:
Here's a shortened link to google
And here's the relevant javascript, which will use XMLHttpRequest to fetch the expanded URL and then update the title
var myRequest;
var mousedOverElement;
var isLoading = false;
function myFunction(anObject) {
if (isLoading == false) {
isLoading = true;
mousedOverElement = anObject;
var link = anObject.getAttribute('href');
var encodedURL = encodeURI(link);
var url = 'http://is.gd/forward.php?format=simple&shorturl=' + encodedURL;
myRequest = new XMLHttpRequest();
myRequest.open("GET", url);
myRequest.onreadystatechange = onStateChange;
myRequest.send();
}
}
function onStateChange() {
if (myRequest.readyState==4) {
if (myRequest.status==200) {
mousedOverElement.setAttribute('title',myRequest.responseText);
}
isLoading = false;
}
}
The problem is, when I hover over the link, and then stop moving the cursor, the title attribute is set properly, but the tooltip is not shown. I have to move the mouse again to make the tooltip show up. I don't necessarily have to move the cursor off of the link and then back over it, but simply moving a few pixels while remaining hovered over the link will do the trick.
I know that the title is being set properly from a combination of using the Web Inspector and the Javascript debugger in Safari. In fact, pretty much as soon as I hover over the link, I see the Web Inspector's view of the DOM in the "elements" tab update with the new title. But, if I take my hand off of the mouse, the tooltip never shows.
My assumption here is that WebKit only shows a tooltip when the user is moving the mouse. Is there a way to sort of "wake up" webkit, even if the cursor is not moving? Or am I better off implementing this with some of my own DHTML-ish magic instead of relying on the title attribute?
What about an element (move it over the anchor) or a wrapper (positive z-index) with a transparent background which will (onmouseover):
first add the anchor's title (you will have to modify your function)
and then change its (negative for the covering element) z-index (effectively putting the anchor in the foreground)
This way the title will be readily available. If necessary you can add a setTimeout() between step 1 and 2.
Or you could simply use setAttributeNode to modify the title attribute value.
You said
"The problem is, when I hover over the
link, and then stop moving the cursor,
the title attribute is set properly,
but the tooltip is not shown."
Its likely that because the title did not exist when you started the mouse hover, it could not display any tooltip (there was nothing to display). So no tooltip will appear. When you move the mouse again, this time it does have a title attribute, so it can display a tooltip. Theres not much you can do about that, its just how the browser works.
Instead your could try using a jQuery tooltip: http://www.reynoldsftw.com/2009/03/10-excellent-tooltip-plugins-with-jquery/
With jQuery you should be able control it so that a tooltip appears as soon as the title is set.

Resources