diff options
Diffstat (limited to 'docroot/classes/layouts/layout.primary.class.js')
-rwxr-xr-x | docroot/classes/layouts/layout.primary.class.js | 411 |
1 files changed, 411 insertions, 0 deletions
diff --git a/docroot/classes/layouts/layout.primary.class.js b/docroot/classes/layouts/layout.primary.class.js new file mode 100755 index 0000000..87bc910 --- /dev/null +++ b/docroot/classes/layouts/layout.primary.class.js | |||
@@ -0,0 +1,411 @@ | |||
1 | /* | ||
2 | * Material Experience - Primary Card Layout Class | ||
3 | * | ||
4 | * EYEMG - Interactive Media Group | ||
5 | * Created by Mike Crute (mcrute@eyemg.com) | ||
6 | * Updated by Mike Crute (mcrute@eyemg.com) on 9/26/07 | ||
7 | * | ||
8 | * WARNING: Here be dragons, OK so not as many as before but good luck you poor | ||
9 | * sap. | ||
10 | */ | ||
11 | |||
12 | Card.Layout.Primary = Class.create(); | ||
13 | Object.extend(Object.extend(Card.Layout.Primary.prototype, Card.Layout.prototype), | ||
14 | { | ||
15 | /* | ||
16 | * Initialize the layout class | ||
17 | */ | ||
18 | initialize: function(cframe, data, card) | ||
19 | { | ||
20 | this.cframe = cframe; | ||
21 | this.data = data; | ||
22 | this.card = card; | ||
23 | this.color = this.card.options.color; | ||
24 | this.hasResources = false; | ||
25 | |||
26 | var direction = data.template.replace(/narrow-/,''); | ||
27 | this.direction = direction ? direction : 'left'; | ||
28 | this.oppositeDirection = (direction == 'left') ? 'right' : 'left'; | ||
29 | }, | ||
30 | |||
31 | /* | ||
32 | * Set the column content. This can be flash, an image or an iframe. | ||
33 | */ | ||
34 | setColumn: function(url, direction, contTitle) | ||
35 | { | ||
36 | var content = Builder.node('div', { style: 'float: ' + this.oppositeDirection }); | ||
37 | var myCol = direction + 'Col'; | ||
38 | |||
39 | if (/swf$/.test(url)) // Flash | ||
40 | { | ||
41 | content.innerHTML = new SWFObject(url, 'cardFlash', 580, 479, 9, '#FFFFFF').getSWFHTML(); | ||
42 | } | ||
43 | else if (/(png|gif|jpg|jpeg)$/.test(url)) // Image | ||
44 | { | ||
45 | content = Builder.node('img', | ||
46 | { | ||
47 | src: url, | ||
48 | alt: contTitle, | ||
49 | title: contTitle, | ||
50 | style: 'float: ' + this.oppositeDirection | ||
51 | }); | ||
52 | } | ||
53 | else // iFrame | ||
54 | { | ||
55 | // Can't use DOM methods because IE is allergic | ||
56 | content.innerHTML = '<iframe ' + | ||
57 | 'src = "' + url + '" ' + | ||
58 | 'frameborder = "0" ' + | ||
59 | 'scrolling = "auto" ' + | ||
60 | 'width = "580" ' + | ||
61 | 'height = "480" ' + | ||
62 | 'id = "wide_content" ' + | ||
63 | 'name = "wide_content" ' + | ||
64 | '></iframe>'; | ||
65 | } | ||
66 | |||
67 | // We need to replace the content of the column if it exists to | ||
68 | // facilitate changing content later on (i.e. thumbnails) | ||
69 | if (typeof this[myCol] != 'undefined') | ||
70 | { | ||
71 | this.cframe.replaceChild(content, this[myCol]); | ||
72 | this[myCol] = content; | ||
73 | } | ||
74 | else | ||
75 | { | ||
76 | this[myCol] = this.cframe.appendChild(content); | ||
77 | } | ||
78 | |||
79 | }, | ||
80 | |||
81 | /* | ||
82 | * Build the resource (more information) list. | ||
83 | */ | ||
84 | getResourceList: function() | ||
85 | { | ||
86 | // Only run if we need to | ||
87 | if (!this.data.resources) | ||
88 | { | ||
89 | return; | ||
90 | } | ||
91 | |||
92 | var numResources = 0; | ||
93 | var iter = 0; | ||
94 | var limit = 5; | ||
95 | this.hasResources = true; | ||
96 | |||
97 | this.resourceContainer = this.contentArea.appendChild( | ||
98 | Builder.node('div', | ||
99 | [ | ||
100 | Builder.node('h2', { style: 'color: ' + this.card.options.color }, Strings.moreInfo), | ||
101 | this.resources = Builder.node('ul', { className: 'resourceList' }) | ||
102 | ] | ||
103 | )); | ||
104 | |||
105 | this.data.resources.each(function(item) | ||
106 | { | ||
107 | // Limit the number of allowable resources | ||
108 | if (typeof item == 'undefined' || ++iter > limit) | ||
109 | { | ||
110 | return; | ||
111 | } | ||
112 | |||
113 | numResources++; | ||
114 | |||
115 | this.resources.appendChild(Builder.node('li', | ||
116 | Builder.node('a', | ||
117 | { | ||
118 | href: item.link + '?entrypoint=DESIGNER', | ||
119 | target: '_new', | ||
120 | style: 'color: ' + this.color | ||
121 | }, item.title) | ||
122 | )); | ||
123 | }.bind(this)); | ||
124 | }, | ||
125 | |||
126 | /* | ||
127 | * Set the contents of the narrow column. | ||
128 | */ | ||
129 | setHTML: function(content) | ||
130 | { | ||
131 | this.htmlDiv.innerHTML = content; | ||
132 | }, | ||
133 | |||
134 | /* | ||
135 | * Setup the thumbnails. | ||
136 | */ | ||
137 | getThumbnails: function() | ||
138 | { | ||
139 | // Only run if we need to | ||
140 | if (this.data.media.size() <= 1) | ||
141 | { | ||
142 | return; | ||
143 | } | ||
144 | |||
145 | var iter = 0; | ||
146 | var limit = 5; // Includes main media file | ||
147 | var lData = this.data.media; | ||
148 | |||
149 | this.thumbStrip = this.contentArea.appendChild(Builder.node('div', { className: 'thumbStrip' })); | ||
150 | |||
151 | // Add the main media file to the data array | ||
152 | lData.push( | ||
153 | { | ||
154 | thumb: this.data.contentWide[0].thumb, | ||
155 | url: this.data.contentWide[0].url | ||
156 | }); | ||
157 | |||
158 | this.data.media.each(function(item) | ||
159 | { | ||
160 | // Limit the number of thumbnails | ||
161 | if (typeof item == 'undefined' || ++iter > limit) | ||
162 | { | ||
163 | return; | ||
164 | } | ||
165 | |||
166 | var mediaPiece = this.thumbStrip.appendChild( | ||
167 | Builder.node('img', | ||
168 | { | ||
169 | src: item.thumb, | ||
170 | className: 'mediaThumb' | ||
171 | }) | ||
172 | ); | ||
173 | |||
174 | Event.observe(mediaPiece, 'click', function() | ||
175 | { | ||
176 | this.setColumn(item.url, this.direction, ''); | ||
177 | }.bindAsEventListener(this)); | ||
178 | }.bind(this)); | ||
179 | }, | ||
180 | |||
181 | /* | ||
182 | * Clean up the data. | ||
183 | */ | ||
184 | _cleanData: function() | ||
185 | { | ||
186 | var lData = this.data.contentNarrow[0].htmlContent; | ||
187 | this.data.contentNarrow[0].htmlContent = lData.replace(/<a/gi, '<a style="color: '+this.color+'"'); | ||
188 | }, | ||
189 | |||
190 | /* | ||
191 | * Calculate the heights of various interface elements for use in | ||
192 | * laying out the page. | ||
193 | */ | ||
194 | _calculateHeights: function() | ||
195 | { | ||
196 | // This data structure will hold the heights of all the elements | ||
197 | // in the narrow column for use in dynamically calculating the | ||
198 | // layout of the column. | ||
199 | this.heightTable = | ||
200 | { | ||
201 | headline : this.headLine ? this.headLine.getHeight() : 0, | ||
202 | content : this.htmlDiv ? this.htmlDiv.getHeight() : 0, | ||
203 | thumbnails : this.thumbStrip ? this.thumbStrip.getHeight() : 0, | ||
204 | resources : this.resourceContainer ? this.resourceContainer.getHeight() : 0, | ||
205 | paddingFactor : !Prototype.Browser.IE ? 40 : 0 | ||
206 | }; | ||
207 | |||
208 | // If there is no headline IE comes up with a ridiculous height for some | ||
209 | // reason so we correct for that here. | ||
210 | if (Prototype.Browser.IE && this.data.contentNarrow[0].title.length == 0) | ||
211 | { | ||
212 | this.heightTable.headline = 0; | ||
213 | } | ||
214 | |||
215 | // A variety of exceptions/tweaks for IE6 found by testing every combination | ||
216 | // of layouts and finding the variance. There isn't much of another way to | ||
217 | // do it. | ||
218 | if (Prototype.Browser.IE) | ||
219 | { | ||
220 | this.heightTable.thumbnail += 2; | ||
221 | this.heightTable.content += 24; | ||
222 | } | ||
223 | |||
224 | if (Prototype.Browser.IE && this.resourceContainer) | ||
225 | { | ||
226 | this.heightTable.resources -= 30; | ||
227 | } | ||
228 | |||
229 | if (Prototype.Browser.IE && this.htmlDiv && this.thumbStrip && !this.resourceContainer) | ||
230 | { | ||
231 | this.heightTable.thumbnails += 10; | ||
232 | } | ||
233 | |||
234 | |||
235 | if (Prototype.Browser.IE && this.resourceContainer && !this.thumbStrip) | ||
236 | { | ||
237 | this.heightTable.resources += 70; | ||
238 | } | ||
239 | |||
240 | // Calculate the height available for content | ||
241 | this.heightTable.avaliableForContent = SME.sizes.innerCard.height - ( | ||
242 | this.heightTable.headline + | ||
243 | this.heightTable.thumbnails + | ||
244 | this.heightTable.resources + | ||
245 | this.heightTable.paddingFactor | ||
246 | ); | ||
247 | }, | ||
248 | |||
249 | /* | ||
250 | * Setup the scroll bar on the wide content area. | ||
251 | */ | ||
252 | _setupScroller: function() | ||
253 | { | ||
254 | // We only want to show the scroll bar if there is a need for it | ||
255 | if (this.heightTable.content < this.heightTable.avaliableForContent) | ||
256 | { | ||
257 | return; | ||
258 | } | ||
259 | |||
260 | this.contentArea.appendChild( | ||
261 | this.scrollCont = Builder.node('div', | ||
262 | { | ||
263 | style: 'border-left: 1px solid ' + this.card.options.color + ';' + | ||
264 | 'width: 1px; right: 0px; position: absolute; ' + | ||
265 | 'height:' + this.heightTable.avaliableForContent + 'px; ' + | ||
266 | 'top: ' + (this.heightTable.headline + 10) + 'px;' | ||
267 | }, | ||
268 | |||
269 | this.scrollBar = Builder.node('img', | ||
270 | { | ||
271 | src: 'images/pill.gif', | ||
272 | style: 'display: block; margin-left: -3px; cursor: move; ' + | ||
273 | 'background: ' + this.card.options.color + ';' | ||
274 | }) | ||
275 | )); | ||
276 | |||
277 | new Control.Slider(this.scrollBar, this.scrollCont, | ||
278 | { | ||
279 | axis: 'vertical', | ||
280 | range: $R(0, this.heightTable.content), | ||
281 | |||
282 | onSlide: function(value) | ||
283 | { | ||
284 | this.htmlDiv.scrollTop = value; | ||
285 | }.bind(this) | ||
286 | }); | ||
287 | |||
288 | }, | ||
289 | |||
290 | /* | ||
291 | * Main function to layout the card. | ||
292 | */ | ||
293 | layout: function() | ||
294 | { | ||
295 | this._cleanData(); | ||
296 | |||
297 | this.setColumn(this.data.contentWide[0].url, this.direction, this.data.contentWide[0].title); | ||
298 | |||
299 | this.contentArea = this.cframe.appendChild( | ||
300 | Builder.node('div', { className: 'narrowCol' }, | ||
301 | this.headLine = Builder.node('h1', { style: 'color: ' + this.color }, this.data.contentNarrow[0].title) | ||
302 | ) | ||
303 | ); | ||
304 | |||
305 | // We've gotta set the width here otherwise the height | ||
306 | // calculations will be incorrect | ||
307 | this.htmlDiv = Builder.node('div', { style: 'width: 98%; overflow: hidden; width: 300px;' }); | ||
308 | |||
309 | // Must set this early on otherwise there is no way to determine | ||
310 | // the actual height of the content div | ||
311 | this.setHTML(this.data.contentNarrow[0].htmlContent); | ||
312 | this.contentArea.appendChild(this.htmlDiv); | ||
313 | |||
314 | this.getResourceList(); | ||
315 | this.getThumbnails(); | ||
316 | |||
317 | // IE doesn't let prototype mess with the default object | ||
318 | // prototypes so we have to manually extend them. Sigh... | ||
319 | [ | ||
320 | this.headLine, | ||
321 | this.htmlDiv, | ||
322 | this.thumbStrip, | ||
323 | this.resourceContainer, | ||
324 | this.contentArea | ||
325 | ].each(Element.extend); | ||
326 | |||
327 | // Set these styles up here or we get a -21px bug in our | ||
328 | // calculation code | ||
329 | this.contentArea.setStyle( | ||
330 | { | ||
331 | width: '310px', | ||
332 | position: 'absolute', | ||
333 | top: '0px' | ||
334 | }); | ||
335 | |||
336 | this._calculateHeights(); | ||
337 | this._setupScroller(); | ||
338 | |||
339 | // We set this last, after all the height calculations are | ||
340 | // completed. That makes it a lot easier to work with. | ||
341 | this.htmlDiv.setStyle({ height: this.heightTable.avaliableForContent + 'px' }); | ||
342 | |||
343 | // Webkit doesn't pad things correctly | ||
344 | if (this.direction == 'left') | ||
345 | { | ||
346 | this.contentArea.setStyle({ left: '10px' }); | ||
347 | } | ||
348 | else | ||
349 | { | ||
350 | this.contentArea.setStyle({ right: '10px' }); | ||
351 | } | ||
352 | |||
353 | // If this is an intro card do the intro card stuff. | ||
354 | if (this.data.template == 'intro') | ||
355 | { | ||
356 | this._doIntro(); | ||
357 | } | ||
358 | |||
359 | return this; | ||
360 | }, | ||
361 | |||
362 | /* | ||
363 | * Setup an intro card. Because intro cards aren't really that much | ||
364 | * different from a basic card and because class inheritance sucks in | ||
365 | * Prototype > 1.6 I'm just going to add this into here. | ||
366 | */ | ||
367 | _doIntro: function() | ||
368 | { | ||
369 | this.contentArea.appendChild(Builder.node('div', { className: 'skipbox' }, | ||
370 | this.skipLink = Builder.node('a', { href: '#tablehome', className: 'skiplink' }, | ||
371 | [ | ||
372 | Strings.skipButton, | ||
373 | Builder.node('img', { src: 'images/arrow_right_grey.gif', className: 'skipimg' }) | ||
374 | ]) | ||
375 | )); | ||
376 | }, | ||
377 | |||
378 | /* | ||
379 | * Throw the card into a popup window for printing. | ||
380 | */ | ||
381 | print: function() | ||
382 | { | ||
383 | var wind = window.open('', '', 'width=' + SME.sizes.innerCard.width + ',height=' + (SME.sizes.innerCard.height + 60)); | ||
384 | |||
385 | with (wind) | ||
386 | { | ||
387 | with (document) | ||
388 | { | ||
389 | write('<html><head><style type="text/css">@import url(application.css); .narrowCol{top: 30px !important;}</style></head><body>'); | ||
390 | write('<img src="images/logo.jpg" style="display: block; margin: 5px 0px 30px 5px;"/>'); | ||
391 | write(this.cframe.innerHTML); | ||
392 | write('</body></html>'); | ||
393 | close(); | ||
394 | } | ||
395 | |||
396 | print(); | ||
397 | close(); | ||
398 | } | ||
399 | |||
400 | return true; | ||
401 | }, | ||
402 | |||
403 | /* | ||
404 | * Debug the card layout. Generally this should be used to spot out | ||
405 | * data issues. But it could also be used for other debugging purposes. | ||
406 | */ | ||
407 | _debug: function() | ||
408 | { | ||
409 | |||
410 | } | ||
411 | }); \ No newline at end of file | ||