PDA

View Full Version : Unobtrusive Bookmark Script Works Too Well, Not A Good Thing



Jules Manson
12-24-2005, 03:29 PM
Dear good people:

I am new to forums so please forgive me if I sound dry and matter-of-fact. After all programming is a very dry discipline but one that bring many rewards. I am self-taught at client-side scripting and I still have a lot to learn but my ego is usually too big to ask for help however sometimes we all need to put our ego aside. I have searched every corner and under every rock on the web looking for a solution before coming here. I recieved help from others at other sites however it did not solve this problem because they did not bother to test their own solutions or simply because I did not understand their responses. If you do wish to help me please test my code and your own solution before replying. Below I post the HTML and script to use as a template.

[WHAT DOES WORK AND COAUTHOR CREDIT GIVEN FOR BEST SOLUTION]

Unobtrusive DOM Scripting (http://domscripting.webstandards.org/?page_id=2) is not a new phenomena however like AJAX it has now just started to take hold among professionals. Currently no bookmark script exists that I know of that is unobtrusive and will automatically grab the URL and Title off a web page. This script does that however it is still "buggy" (see my requests for help). Once this script is debugged I will post it at several well known web sites and Dynamic Drive if they accept it. I will of course give coauthor credit along with a link to their web site for the best solution given.

[REQUEST FOR HELP - SHORT VERSION]

I want the code in this bookmark1.html (http://members.aol.com/oysteinramfjord/bookmark1.html) to behave like this bookmark2.html (http://members.aol.com/oysteinramfjord/bookmark2.html) without adding any javascript inside any tags whatsoever. All javascript must exist inside the head section of the HTML file. Both were tested with Firefox 1.5 and MSIE 6.0 with Windows Me (yes I know I am laughing too). It is more important for this script to work on MSIE. Thank you for considering this problem.

[REQUEST FOR HELP - LONG VERSION]

On both MSIE 6.0 and Firefox 1.5 the script does not wait for the onClick event to activate. On MSIE the bookmark dialog box opens immediately when the page loads. On Firefox one gets the alert message for nonsupporting browsers. Firefox is supposed to support bookmarking via scripts. Both are supposed to wait for an onClick mouse event. My intent in writing this as I did is to completely seperate behavior from structure and presentation. My goal is to eventually link this script externally via a javascript library file. It is more important for this script to work on MSIE. Please, no solutions which require adding inline javascript to my bookmark link. I already know how to do that. The onClick event handler must be contained inside the script which resides in the head section (not the anchor tag). I need to make this unobtrusive so that nonprogrammers can easily edit the HTML. This script will also serve as a model for many other unobtrusive scripts which I have planned. Please examine and test my code to see why it is not waiting for the onClick mouse event before loading. My ultimate goal is to ensure that this cross-browser script works on MSIE, Netscape, Firefox, and Opera. Thank you for considering this problem.

[THE CODE TEMPLATE]

<HTML><HEAD>
<TITLE>UNOBTRUSIVE DOM SCRIPTING - BOOKMARK</TITLE>
<SCRIPT>
function bookFav() {
if (!document.getElementById || !document.all) /* object detection to prevent errors */
{alert("Please use your browser menu to bookmark us!");} /* alert for non-supporting browsers */
else {
var el = document.getElementById("bookmark");
myURL = window.location.href; /* gets url of page to bookmark */
myTitle = document.title; /* gets title of page */
el.onClick = addFav(myURL,myTitle); /* this event is supposed to open the bookmark dialog */
}
}
function addFav(aURL,aTitle){
if (document.all) /* is this MSIE? */
{window.external.AddFavorite(aURL,aTitle);} /* if yes then call bookmark for MSIE */
else if(window.sidebar) {window.sidebar.addPanel(aURL,aTitle,"");} /* else call bookmark for NS&FF */
return false;
}
window.onload=bookFav;
</SCRIPT>
</STYLE>
</HEAD>
<BODY>
Please <A id="bookmark" href="#">bookmark</A> this site.
</BODY>
</HTML>

jscheuer1
12-24-2005, 04:18 PM
This may not be the only problem but the rest looks good on casual inspection. Sorry I don't have time at the moment to test it as you request. See if this doesn't take care of it - change:


el.onClick = addFav(myURL,myTitle);

to:


el.onClick = function(){addFav(myURL,myTitle);return false;}

You might want to add the touch of intentionally declaring myURL and myTitle as global variables, which they need to be for this to work this way. However, they should already be globals the way your code is written. To make that intentional add:


var myURL, myTitle;

before this line:


function bookFav() {

Jules Manson
12-24-2005, 08:43 PM
Thank you for replying John. Your reply was very clear and concise but unfortunately it did not work. Although the bookmark dialog box did not pop up instantly and no errors occured (tested only with MSIE 6.0) the link did not respond either as it should have. I suspect we may be close to a solution. I experimented with variations of your method with no positive results. The declaring of global variables is not necessary because a test of these variables with an alert inside the addFav function yielded correct results.

jscheuer1
12-24-2005, 09:55 PM
This worked here, except that being local, I guess prevented any bookmark:


<HTML><HEAD>
<TITLE>UNOBTRUSIVE DOM SCRIPTING - BOOKMARK</TITLE>
<SCRIPT>
var myURL, myTitle;
function bookFav() {
if (!document.getElementById && !document.all) /* object detection to prevent errors */
{alert("Please use your browser menu to bookmark us!");} /* alert for non-supporting browsers */
else {
var el = document.all? document.all['bookmark'] : document.getElementById("bookmark");
myURL = window.location.href; /* gets url of page to bookmark */
myTitle = document.title; /* gets title of page */
el.onclick = function(){addFav(myURL,myTitle);return false;}; /* this event is supposed to open the bookmark dialog */
}
}
function addFav(aURL,aTitle){
if (document.all) /* is this MSIE? */
{window.external.AddFavorite(aURL,aTitle);} /* if yes then call bookmark dialog for MSIE */
else if(window.sidebar) {window.sidebar.addPanel(aURL,aTitle,"");} /* else call bookmark dialog for NS&FF */
}
window.onload=bookFav;
</SCRIPT>
</STYLE>
</HEAD>
<BODY>
Please <A id="bookmark" href="#">bookmark</A> this site.

<P>This bookmark dialog loads immediately on Windows Internet Explorer 6.0. I do not want that. It is supposed to wait for the onclick event handler which should only work when the link is clicked. Please view the source code on this HTML file for the code that I wish to edit. I do not want any javascript added to any HTML tags. The script in the head of this file will eventually be moved to an external javascript library file.
</BODY>
</HTML>

Notes: Declaring the variables globally is just good form and may matter in certain unforeseen circumstances. Object detection needs to be used subsequently to be of much use. In javascript, it is onclick, not onClick. Your previous object detection excluded any browser that doesn't support document.all. Adding an event to an element in this manner requires it be a function in its own right.

mwinter
12-24-2005, 11:02 PM
Just how 'unobtrusive' are you thinking? Personally, I think the general idea of bookmarking scripts are pointless. I know of three ways to do it, so a potentially non-functioning fourth alternative (depending on my browser and its configuration) seems unnecessary and inferior.

That said, as I see it there are three potential scenarios.


The fully-functional. The browser supports at least one of the implemented ways of adding a bookmark, has sufficient DOM support (if necessary), and have client-side scripting support enabled.
The partial failure. The browser has client-side scripting support enabled, but that support fails to provide one of the other features mentioned above.
Complete failure. The browser either doesn't implement a script engine, or that support has been disabled at the user's request.
It's clear what should happen in the first scenario, but what do you plan for the second? Presenting something that claims to work but doesn't (and showing a dialogue box telling the user to "use [their] browser menu" isn't 'working') fails to be either professional or unobtrusive.

There are, perhaps, two solutions:


Include the text, "please bookmark this site" somewhere in the document and then, given adequate support, transform "bookmark this site" into something that at least resembles a link and will perform the advertised operation.
Given adequate support, insert both text and behaviour into the document at some point.
The difference, in case it's not clear, is whether the request to add a bookmark is always present, or only if bookmarking is possible using the script. The former will be more easier for a third party to use, especially if they are not that familiar with the DOM.



.link {
background: transparent;
color: #0000ff;
cursor: pointer;
cursor: hand;
text-decoration: underline;
}


this.onload = function() {
var listener = ('object' == typeof external)
? function() {external.AddFavorite(url, title); return false;}
: ('object' == typeof sidebar) && ('function' == typeof sidebar.addPanel)
? function() {sidebar.addPanel(title, url, ''); return false;}
: null,
title = document.title,
url = document.URL,
bookmark;

if(listener && document.getElementById
&& (bookmark = document.getElementById('bookmark'))
&& ('string' == typeof title)
&& ('string' == typeof url))
{
bookmark.className = 'link';
bookmark.onclick = listener;
}
bookmark = listener
= null;
};


<p>Please <span id="bookmark">bookmark this site</span>.</p>




if (!document.getElementById || !document.all) /* object detection to prevent errors */
Feature detection is the correct approach to take, wherein a more or less one-to-one test-to-feature examination of the host enviroment is used to determine whether a particular operation can be executed. Trying to infer support based on the presence of unrelated objects, properties or methods is typically doomed to failure.



myURL = window.location.href; /* gets url of page to bookmark */
myTitle = document.title; /* gets title of page */
Why are these global?



if (document.all) /* is this MSIE? */
Browser detection, by virtually any method, is also doomed to failure. Not only will IE type-convert that expression to true, but so will Opera, Omniweb, Konqueror, Safari, NetFront, iCab, and IceBrowser. There may even be others.

Mike