Hey all, My first real rails app is coming along pretty well. I''m normally a high school teacher, but I''ve spent the summer working on a literacy project at the Electronic Frontier Foundation (EFF). The final project presentation is a web site. I''ve been hacking my way through it, but I am at a sticking point and I just can''t find a solution. Reference this example: http://commontext.com/articles/show/6 The display looks perfect on firefox. #1) On IE, the side definitions don''t show up at all. Any tips how I might restructure the javascript to accomplish the same effect? #2) The most important problem is that it doesn''t print properly. The definitions only show up on the first page. I''ve dug around for tutorials about CSS & printing, but haven''t learned much. Apparently there was (at one time) a bug that made floated sections not print properly, but I am pretty sure that is not the problem here because the main text prints fine (it''s in a floated section) and it still doesn''t work when the float statement is removed. If anyone has genius ideas about how to completely reimplement this effect I''m all ears. Rewriting the views/etc is no problem whatsoever. Thanks for your time and expertise, Jeff Casimir PS: I know the site doesn''t implement any security at the moment. All of the data is backed up and safe. The site is, for now, only used for testing.
The advice I can give may not be what you want to hear. A quick look at the code shows that you are generating JavaScript on the server to that repositions the definitions to be vertically aligned with where they appear in the text? You may have problems with differences in the DOMs (Document Object Models) between Firefox and IE. Not to mention Safari, Opera and older versions of all these (which you may not care about). I think the standard says the Javascript should be in the <head>, but I most browsers are pretty forgiving about this. As an alternative, you might look at the <abbr> and <acronym> tags, and/or making use of the "title" attribute and use the browser equivalent of tool-tips to show the definitions.
Steve, Thanks for your thoughts... - On the positioning of the javascript, I was told that it would have to appear someplace after the elements which it attempts to find (find_element_by_id or whatever) so I put it at the bottom. Nevertheless, I will work on some experiments with moving it to the top. - I should have mentioned tooltips in my previous email. I agree that tooltips, in one way or another, are an almost ideal way to achive this functionality. However, the articles are going to be printed much more than they are read. Obviously tooltips wouldn''t suffice for printing without a hack like inserting the definition directly into the text inside parentheses or something. I think that would too greatly obfuscate the actual text. You''ve got me mulling over a new idea, though. I wonder if the definitions could be planted into the article text, wrapped in span tags, then pulled out to the right using absolute positioning? It sounds possible, but I can''t think of a way to avoid the "collisions" of words appearing on the same or nearby lines. -Jeff Steve Downey wrote:>The advice I can give may not be what you want to hear. A quick look at the >code shows that you are generating JavaScript on the server to that repositions >the definitions to be vertically aligned with where they appear in the text? > >You may have problems with differences in the DOMs (Document Object Models) >between Firefox and IE. Not to mention Safari, Opera and older versions of all >these (which you may not care about). > >I think the standard says the Javascript should be in the <head>, but I most >browsers are pretty forgiving about this. > >As an alternative, you might look at the <abbr> and <acronym> tags, and/or >making use of the "title" attribute and use the browser equivalent of tool-tips >to show the definitions. > >_______________________________________________ >Rails mailing list >Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org >http://lists.rubyonrails.org/mailman/listinfo/rails >
(Again, kind of changing what you were trying to do) Take all your definitions and put them in a div at the bottom of the page with class of "print-only". In your "screen" stylesheet use the "display: none;" so it''s not visible in the browser but will be in the printout. If you want to be fancy you could even have your "print" stylesheet to a page-eject so the keywords are on a page by themselves. See @media types and page-break (e.g.: http://www.w3schools.com/css/pr_print_pageba.asp)
On Sunday 31 July 2005 03:00, Jeff Casimir wrote:> On the positioning of the javascript, I was told that it would have > to appear someplace after the elements which it attempts to find > (find_element_by_id or whatever) so I put it at the bottom. > Nevertheless, I will work on some experiments with moving it to the > top.You''ve been misled. You have to make sure that your JavaScript code is *executed* only after the elements it presupposes exist. This can be achieved by putting the scripts at the bottom of the page, but has the drawback of cluttering the page with JavaScript. A better way is to put the script code into the head element. Even better is putting it into an external file. So, when the script comes before the elements it refers to, how do you make sure that it is run after the elements have been create? Simple: Put the script into a function and tell your browser to execute that function after the page is loaded: function myfunc() { // do whatever needs doing } Event.observe(window, ''load'', myfunc) The latter is not standard JavaScript, but defined in prototype.js. I recommend to use it over the lower-level functions such as addEventListener and attachEvent, as Event.observe takes care of smoothing out browser differences. Also, I notice that you have (generate?) a lot of repetitive code. That''s not good, generated or hand-written. Some abstraction is clearly in order! Again with the help of prototype.js var Marginalia = Class.create(); Marginalia.prototype = { initialize: function() { this.bottomOfLastast = 0; this.keywordTop; this.buffer = 5; }, adjustKeyword: function(keyword, note) { keyword = $(keyword); note = $(note); this.keywordTop = keyword.offsetTop; if(this.bottomOfLast < this.keywordTop) { note.style.top = keywordTop + ''px''; } else { note.style.top = this.bottomOfLast + this.buffer + ''px''; this.bottomOfLast = note.offsetTop + note.offsetHeight; } } } The above code preferably goes into an external JavaScript file. But then, how do you hook it up with the keywords and notes in your page? Unobtrusively! First, I recommend to mark up keywords slightly differently: Instead of <span id="keyword_small_fry"><span class="keyword">small fry</span></span> and <div style="position:absolute" id="note_small_fry"><div class="note"><span class="keyword">small fry</span>: ... </div></div> use <span id="keyword_small_fry" class="keyword">small fry</span> and <div style="position:absolute" id="note_small_fry" class="note"> <span class="keyword">small fry</span>: ... </div> Then you need to get hold of the keywords: Marginalia.prototype = { initialize: function(where) { this.where = $(where); this.bottomOfLastast = 0; this.keywordTop; this.buffer = 5; }, adjustKeyword: function(keyword, note) { //... }, applyToKeywords: function() { keywords = this.findKeywords(this.where); for (var i = 0; i < keywords.length; i++) { var keyword = keywords[i]; this.adjustKeyword(keyword, keyword.id.replace(/keyword_/, ''note_'')); } }, findKeywords(where) { var keywords = []; var spans = where.getElementsByTagName(''span''); for (var i = 0; i < span.length; i++) { var span = spans[i]; if (Element.hasClassName(span, ''keyword'')) { keywords.push(span); } } return keywords; } } Then, to have the script do its work Event.observe(window, ''load'', function() { var marge = new Marginalia(''article''); marge.applyToKeywords(); }); You can put *all* of this code away in an external script file and don''t have to write or generate any additional code. Please note, though, that I have not tested the code at all. Incidentally, for the hooking up you could also use behaviour.js (http://www.ripcord.co.nz/behaviour/), which has recently been hotly discussed in here. All that said, and this might come as a denouement, when all you want to achieve is a layout with two columns, you can have it without any JavaScript at all. In your article.css, add absolute positioning to .article .article { position: absolute; ... } and remove the unnecessary inline-styles from the keyword definitions. HTH, Michael -- Michael Schuerig Nothing is as brilliantly adaptive mailto:michael-q5aiKMLteq4b1SvskN2V4Q@public.gmane.org as selective stupidity. http://www.schuerig.de/michael/ --A.O. Rorty, The Deceptive Self