Merge lp:~alexharrington/xibo/server-160-rc1-preview into lp:xibo/1.6
- server-160-rc1-preview
- Merge into ponswinnecke
Proposed by
Alex Harrington
Status: | Rejected |
---|---|
Rejected by: | Alex Harrington |
Proposed branch: | lp:~alexharrington/xibo/server-160-rc1-preview |
Merge into: | lp:xibo/1.6 |
Diff against target: |
1723 lines (+1370/-99) (has conflicts) 17 files modified
server/install/database/66.sql (+13/-1) server/install/master/data.sql (+11/-3) server/lib/modules/module.class.php (+58/-2) server/lib/pages/content.class.php (+7/-0) server/lib/pages/layout.class.php (+9/-2) server/lib/pages/module.class.php (+1/-78) server/lib/pages/preview.class.php (+125/-0) server/modules/flash.module.php (+12/-1) server/modules/image.module.php (+64/-3) server/modules/preview/html-preview.css (+92/-0) server/modules/preview/html-preview.js (+499/-0) server/modules/preview/html5Preloader.js (+448/-0) server/modules/video.module.php (+12/-1) server/theme/default/html/layout_designer.php (+2/-1) server/theme/default/html/layout_page_grid.php (+2/-2) server/theme/default/html/library_page_grid.php (+13/-3) server/theme/default/js/xibo-layout-designer.js (+2/-2) Text conflict in server/install/database/66.sql Text conflict in server/install/master/data.sql |
To merge this branch: | bzr merge lp:~alexharrington/xibo/server-160-rc1-preview |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Dan Garner | Needs Fixing | ||
Review via email: mp+206045@code.launchpad.net |
Commit message
Description of the change
First pass HTML5 layout preview
To post a comment you must log in.
- 311. By Alex Harrington
-
[server] Add page security for the new preview page
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'server/install/database/66.sql' |
2 | --- server/install/database/66.sql 2014-01-20 17:50:31 +0000 |
3 | +++ server/install/database/66.sql 2014-02-12 21:14:59 +0000 |
4 | @@ -78,6 +78,7 @@ |
5 | (78, 'User', 'SetPassword', 'manual/single.php?p=users/users#Set_Password'), |
6 | (79, 'DataSet', 'ImportCSV', 'manual/single.php?p=content/content_dataset#Import_CSV'); |
7 | |
8 | +<<<<<<< TREE |
9 | INSERT INTO `setting` ( |
10 | `settingid` , |
11 | `setting` , |
12 | @@ -94,6 +95,17 @@ |
13 | NULL , 'SETTING_LIBRARY_TIDY_ENABLED', 'Off', 'dropdown', NULL , 'On|Off', 'general', '0' |
14 | ); |
15 | |
16 | +======= |
17 | +INSERT INTO `setting` VALUES (`settingid`,`setting`,`value`,`type`,`helptext`,`options`,`cat`,`userChange`) |
18 | +(NULL, 'SENDFILE_MODE', 'Off', 'dropdown', 'When a user downloads a file from the library or previews a layout, should we attempt to use Apache X-Sendfile, Nginx X-Accel, or PHP (Off) to return the file from the library?', 'Off|Apache|Nginx', 'general', '1'); |
19 | + |
20 | +INSERT INTO `pages` (`name`, `pagegroupID`) VALUES |
21 | +('preview', 3); |
22 | + |
23 | +INSERT INTO `lkpagegroup` (`lkpagegroupID`, `pageID`, `groupID`) VALUES |
24 | +(63, 41, 1); |
25 | + |
26 | +>>>>>>> MERGE-SOURCE |
27 | UPDATE `version` SET `app_ver` = '1.6.0-rc1', `XmdsVersion` = 3; |
28 | UPDATE `setting` SET `value` = 0 WHERE `setting` = 'PHONE_HOME_DATE'; |
29 | -UPDATE `version` SET `DBVersion` = '66'; |
30 | \ No newline at end of file |
31 | +UPDATE `version` SET `DBVersion` = '66'; |
32 | |
33 | === modified file 'server/install/master/data.sql' |
34 | --- server/install/master/data.sql 2014-01-20 17:50:31 +0000 |
35 | +++ server/install/master/data.sql 2014-02-12 21:14:59 +0000 |
36 | @@ -152,7 +152,8 @@ |
37 | (37, 'campaign', 3), |
38 | (38, 'transition', 4), |
39 | (39, 'timeline', 3), |
40 | -(40, 'sessions', 9); |
41 | +(40, 'sessions', 9), |
42 | +(41, 'preview', 3); |
43 | |
44 | INSERT INTO `menuitem` (`MenuItemID`, `MenuID`, `PageID`, `Args`, `Text`, `Class`, `Img`, `Sequence`, `External`) VALUES |
45 | (1, 1, 2, NULL, 'Schedule', NULL, NULL, 1, 0), |
46 | @@ -251,9 +252,14 @@ |
47 | (63, 'GLOBAL_THEME_NAME', 'default', 'text', 'The Theme to apply to all pages by default', NULL, 'general', 1), |
48 | (64, 'DEFAULT_LAT', '51.504', 'text', 'The Latitude to apply for any Geo aware Previews', NULL, 'general', 1), |
49 | (65, 'DEFAULT_LONG', '-0.104', 'text', 'The Longitude to apply for any Geo aware Previews', NULL, 'general', 1), |
50 | +<<<<<<< TREE |
51 | (66, 'SCHEDULE_WITH_VIEW_PERMISSION', 'No', 'dropdown', 'Should users with View permissions on displays be allowed to schedule to them?', 'Yes|No', 'permissions', '1'), |
52 | (67, 'SETTING_IMPORT_ENABLED', 'Off', 'dropdown', NULL , 'On|Off', 'general', '0'), |
53 | (68, 'SETTING_LIBRARY_TIDY_ENABLED', 'Off', 'dropdown', NULL , 'On|Off', 'general', '0'); |
54 | +======= |
55 | +(66, 'SCHEDULE_WITH_VIEW_PERMISSION', 'No', 'dropdown', 'Should users with View permissions on displays be allowed to schedule to them?', 'Yes|No', 'permissions', '1'), |
56 | +(69, 'SENDFILE_MODE', 'Off', 'dropdown', 'When a user downloads a file from the library or previews a layout, should we attempt to use Apache X-Sendfile, Nginx X-Accel, or PHP (Off) to return the file from the library?', 'Off|Apache|Nginx', 'general', '1'); |
57 | +>>>>>>> MERGE-SOURCE |
58 | |
59 | INSERT INTO `usertype` (`usertypeid`, `usertype`) VALUES |
60 | (1, 'Super Admin'), |
61 | @@ -303,7 +309,9 @@ |
62 | (38, 19, 1), |
63 | (48, 5, 1), |
64 | (51, 7, 1), |
65 | -(54, 24, 1); |
66 | +(54, 24, 1), |
67 | +(63, 41, 1); |
68 | + |
69 | |
70 | INSERT INTO `lktemplategroup` (`LkTemplateGroupID`, `TemplateID`, `GroupID`, `View`, `Edit`, `Del`) VALUES |
71 | (1, 1, 2, 1, 0, 0), |
72 | @@ -330,4 +338,4 @@ |
73 | |
74 | INSERT INTO `datasetcolumntype` (`DataSetColumnTypeID`, `DataSetColumnType`) VALUES |
75 | (1, 'Value'), |
76 | -(2, 'Formula'); |
77 | \ No newline at end of file |
78 | +(2, 'Formula'); |
79 | |
80 | === modified file 'server/lib/modules/module.class.php' |
81 | --- server/lib/modules/module.class.php 2014-01-19 14:06:56 +0000 |
82 | +++ server/lib/modules/module.class.php 2014-02-12 21:14:59 +0000 |
83 | @@ -51,6 +51,7 @@ |
84 | protected $deleteFromRegion; |
85 | protected $showRegionOptions; |
86 | protected $originalUserId; |
87 | + protected $storedAs; |
88 | |
89 | // Track the error state |
90 | private $error; |
91 | @@ -223,7 +224,7 @@ |
92 | $this->assignedMedia = false; |
93 | |
94 | // Load what we know about this media into the object |
95 | - $SQL = "SELECT duration, name, UserId FROM media WHERE mediaID = '$mediaid'"; |
96 | + $SQL = "SELECT duration, name, UserId, storedAs FROM media WHERE mediaID = '$mediaid'"; |
97 | |
98 | Debug::LogEntry('audit', $SQL, 'Module', 'SetMediaInformation'); |
99 | |
100 | @@ -239,6 +240,7 @@ |
101 | $this->duration = $row[0]; |
102 | $this->name = $row[1]; |
103 | $this->originalUserId = $row[2]; |
104 | + $this->storedAs = $row[3]; |
105 | } |
106 | else |
107 | return $this->SetError(__('Unable to find media record with the provided ID')); |
108 | @@ -1896,5 +1898,59 @@ |
109 | // Defaults: Stored media is valid, region specific is unknown |
110 | return ($this->regionSpecific) ? 0 : 1; |
111 | } |
112 | + |
113 | + /** |
114 | + * Return filebased media items to the browser for Download/Preview |
115 | + * @return |
116 | + * @param $download Boolean |
117 | + */ |
118 | + public function ReturnFile($fileName = '') { |
119 | + // Return the raw flash file with appropriate headers |
120 | + $library = Config::GetSetting("LIBRARY_LOCATION"); |
121 | + |
122 | + # If we weren't passed in a filename then use the default |
123 | + if ($fileName == '') { |
124 | + $fileName = $library . $this->storedAs; |
125 | + } |
126 | + |
127 | + $download = Kit::GetParam('download', _REQUEST, _BOOLEAN, False); |
128 | + |
129 | + $size = filesize($fileName); |
130 | + |
131 | + if ($download) { |
132 | + header('Content-Type: application/octet-stream'); |
133 | + header("Content-Transfer-Encoding: Binary"); |
134 | + header("Content-disposition: attachment; filename=\"" . basename($fileName) . "\""); |
135 | + } |
136 | + else { |
137 | + $fi = new finfo( FILEINFO_MIME_TYPE ); |
138 | + $mime = $fi->file( $fileName ); |
139 | + header("Content-Type: {$mime}"); |
140 | + } |
141 | + |
142 | + //Output a header |
143 | + header('Pragma: public'); |
144 | + header('Cache-Control: max-age=86400'); |
145 | + header('Expires: '. gmdate('D, d M Y H:i:s \G\M\T', time() + 86400)); |
146 | + header('Content-Length: ' . $size); |
147 | + |
148 | + // Send via Apache X-Sendfile header? |
149 | + if (Config::GetSetting('SENDFILE_MODE') == 'Apache') { |
150 | + header("X-Sendfile: $fileName"); |
151 | + exit(); |
152 | + } |
153 | + |
154 | + // Send via Nginx X-Accel-Redirect? |
155 | + if (Config::GetSetting('SENDFILE_MODE') == 'Nginx') { |
156 | + header("X-Accel-Redirect: /download/" . $this->storedAs); |
157 | + exit(); |
158 | + } |
159 | + |
160 | + // Return the file with PHP |
161 | + // Disable any buffering to prevent OOM errors. |
162 | + @ob_end_clean(); |
163 | + @ob_end_flush(); |
164 | + readfile($fileName); |
165 | + } |
166 | } |
167 | -?> |
168 | \ No newline at end of file |
169 | +?> |
170 | |
171 | === modified file 'server/lib/pages/content.class.php' |
172 | --- server/lib/pages/content.class.php 2014-02-08 14:55:15 +0000 |
173 | +++ server/lib/pages/content.class.php 2014-02-12 21:14:59 +0000 |
174 | @@ -147,6 +147,13 @@ |
175 | 'text' => __('Permissions') |
176 | ); |
177 | } |
178 | + |
179 | + // Download |
180 | + $row['buttons'][] = array( |
181 | + 'id' => 'content_button_download', |
182 | + 'url' => 'index.php?p=module&mod=' . $row['mediatype'] . '&q=Exec&method=GetResource&download=1&mediaid=' . $row['mediaid'], |
183 | + 'text' => __('Download') |
184 | + ); |
185 | |
186 | // Add to the collection |
187 | $rows[] = $row; |
188 | |
189 | === modified file 'server/lib/pages/layout.class.php' |
190 | --- server/lib/pages/layout.class.php 2014-02-08 14:55:15 +0000 |
191 | +++ server/lib/pages/layout.class.php 2014-02-12 21:14:59 +0000 |
192 | @@ -136,6 +136,7 @@ |
193 | Theme::Set('layout_form_edit_background_url', 'index.php?p=layout&q=BackgroundForm&modify=true&layoutid=' . $this->layoutid); |
194 | Theme::Set('layout_form_savetemplate_url', 'index.php?p=template&q=TemplateForm&layoutid=' . $this->layoutid); |
195 | Theme::Set('layout_form_addregion_url', 'index.php?p=timeline&q=AddRegion&layoutid=' . $this->layoutid); |
196 | + Theme::Set('layout_form_preview_url', 'index.php?p=preview&q=render&ajax=true&layoutid=' . $this->layoutid); |
197 | Theme::Set('layout', $this->layout); |
198 | |
199 | Kit::ClassLoader('campaign'); |
200 | @@ -398,6 +399,12 @@ |
201 | 'text' => __('Schedule Now') |
202 | ); |
203 | |
204 | + $row['buttons'][] = array( |
205 | + 'id' => 'layout_button_preview', |
206 | + 'url' => 'index.php?p=preview&q=render&ajax=true&layoutid=' . $layout['layoutid'], |
207 | + 'text' => __('Preview Layout') |
208 | + ); |
209 | + |
210 | // Only proceed if we have edit permissions |
211 | if ($layout['edit']) { |
212 | |
213 | @@ -545,7 +552,7 @@ |
214 | $bgImageInfo = explode('.', $backgroundImage); |
215 | $bgImageId = $bgImageInfo[0]; |
216 | |
217 | - $thumbBgImage = "index.php?p=module&q=GetImage&id=$bgImageId&width=80&height=80&dynamic"; |
218 | + $thumbBgImage = "index.php?p=module&mod=image&q=Exec&method=GetResource&mediaid=$bgImageId&width=80&height=80&dynamic"; |
219 | } |
220 | else |
221 | { |
222 | @@ -685,7 +692,7 @@ |
223 | $bgImageInfo = explode('.', $bgImage); |
224 | $bgImageId = $bgImageInfo[0]; |
225 | |
226 | - $background_css = "url('index.php?p=module&q=GetImage&id=$bgImageId&width=$width&height=$height&dynamic&proportional=0') top center no-repeat; background-color:$bgColor"; |
227 | + $background_css = "url('index.php?p=module&mod=image&q=Exec&method=GetResource&mediaid=$bgImageId&width=$width&height=$height&dynamic&proportional=0') top center no-repeat; background-color:$bgColor"; |
228 | } |
229 | |
230 | $width = $width . "px"; |
231 | |
232 | === modified file 'server/lib/pages/module.class.php' |
233 | --- server/lib/pages/module.class.php 2014-01-18 09:47:41 +0000 |
234 | +++ server/lib/pages/module.class.php 2014-02-12 21:14:59 +0000 |
235 | @@ -271,82 +271,5 @@ |
236 | $response->Respond(); |
237 | } |
238 | } |
239 | - |
240 | - /** |
241 | - * Returns an image stream to the browser - for the mediafile specified. |
242 | - * @return |
243 | - */ |
244 | - function GetImage() |
245 | - { |
246 | - $db =& $this->db; |
247 | - |
248 | - $mediaID = Kit::GetParam('id', _GET, _INT, 0); |
249 | - $proportional = Kit::GetParam('proportional', _GET, _BOOL, true); |
250 | - $thumb = Kit::GetParam('thumb', _GET, _BOOL, false); |
251 | - $dynamic = isset($_REQUEST['dynamic']); |
252 | - |
253 | - if ($mediaID == 0) |
254 | - die ('No media ID provided'); |
255 | - |
256 | - // Get the file URI |
257 | - $SQL = sprintf("SELECT StoredAs FROM media WHERE MediaID = %d", $mediaID); |
258 | - |
259 | - if (!$file = $db->GetSingleValue($SQL, 'StoredAs', _STRING)) |
260 | - die ('No media found for that media ID'); |
261 | - |
262 | - //File upload directory.. get this from the settings object |
263 | - $library = Config::GetSetting("LIBRARY_LOCATION"); |
264 | - $fileName = $library . $file; |
265 | - |
266 | - // If we are a thumb request then output the cached thumbnail |
267 | - if ($thumb) |
268 | - $fileName = $library . 'tn_' . $file; |
269 | - |
270 | - // If the thumbnail doesnt exist then create one |
271 | - if (!file_exists($fileName)) |
272 | - { |
273 | - Debug::LogEntry('audit', 'File doesnt exist, creating a thumbnail for ' . $fileName); |
274 | - |
275 | - if (!$info = getimagesize($library . $file)) |
276 | - die($library . $file . ' is not an image'); |
277 | - |
278 | - ResizeImage($library . $file, $fileName, 80, 80, $proportional, 'file'); |
279 | - } |
280 | - |
281 | - // Get the info for this new temporary file |
282 | - if (!$info = getimagesize($fileName)) |
283 | - { |
284 | - echo $fileName . ' is not an image'; |
285 | - exit; |
286 | - } |
287 | - |
288 | - if ($dynamic && $info[2]) |
289 | - { |
290 | - $width = Kit::GetParam('width', _GET, _INT); |
291 | - $height = Kit::GetParam('height', _GET, _INT); |
292 | - |
293 | - // dynamically create an image of the correct size - used for previews |
294 | - ResizeImage($fileName, '', $width, $height, $proportional, 'browser'); |
295 | - |
296 | - exit; |
297 | - } |
298 | - |
299 | - if (!$image = file_get_contents($fileName)) |
300 | - { |
301 | - //not sure |
302 | - Debug::LogEntry('audit', "Cant find: $uid", 'module', 'GetImage'); |
303 | - |
304 | - $fileName = 'theme/default/img/forms/filenotfound.png'; |
305 | - $image = file_get_contents($fileName); |
306 | - } |
307 | - |
308 | - $size = getimagesize($fileName); |
309 | - |
310 | - //Output the image header |
311 | - header("Content-type: {$size['mime']}"); |
312 | - |
313 | - echo $image; |
314 | - exit; |
315 | - } |
316 | } |
317 | -?> |
318 | \ No newline at end of file |
319 | +?> |
320 | |
321 | === added file 'server/lib/pages/preview.class.php' |
322 | --- server/lib/pages/preview.class.php 1970-01-01 00:00:00 +0000 |
323 | +++ server/lib/pages/preview.class.php 2014-02-12 21:14:59 +0000 |
324 | @@ -0,0 +1,125 @@ |
325 | +<?php |
326 | +/* |
327 | + * Xibo - Digital Signage - http://www.xibo.org.uk |
328 | + * Copyright (C) 2014 Alex Harrington |
329 | + * |
330 | + * This file is part of Xibo. |
331 | + * |
332 | + * Xibo is free software: you can redistribute it and/or modify |
333 | + * it under the terms of the GNU Affero General Public License as published by |
334 | + * the Free Software Foundation, either version 3 of the License, or |
335 | + * any later version. |
336 | + * |
337 | + * Xibo is distributed in the hope that it will be useful, |
338 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
339 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
340 | + * GNU Affero General Public License for more details. |
341 | + * |
342 | + * You should have received a copy of the GNU Affero General Public License |
343 | + * along with Xibo. If not, see <http://www.gnu.org/licenses/>. |
344 | + */ |
345 | +defined('XIBO') or die("Sorry, you are not allowed to directly access this page.<br /> Please press the back button in your browser."); |
346 | + |
347 | +class previewDAO |
348 | +{ |
349 | + private $db; |
350 | + private $user; |
351 | + private $auth; |
352 | + private $has_permissions = true; |
353 | + |
354 | + private $layoutid; |
355 | + private $layout; |
356 | + private $retired; |
357 | + private $description; |
358 | + private $tags; |
359 | + |
360 | + private $xml; |
361 | + |
362 | + function __construct(database $db, user $user) |
363 | + { |
364 | + $this->db =& $db; |
365 | + $this->user =& $user; |
366 | + $this->layoutid = Kit::GetParam('layoutid', _REQUEST, _INT); |
367 | + |
368 | + // Include the layout data class |
369 | + include_once("lib/data/layout.data.class.php"); |
370 | + |
371 | + //if we have modify selected then we need to get some info |
372 | + if ($this->layoutid != '') |
373 | + { |
374 | + // get the permissions |
375 | + Debug::LogEntry('audit', 'Loading permissions for layoutid ' . $this->layoutid); |
376 | + |
377 | + $this->auth = $user->LayoutAuth($this->layoutid, true); |
378 | + |
379 | + if (!$this->auth->view) |
380 | + trigger_error(__("You do not have permissions to view this layout"), E_USER_ERROR); |
381 | + |
382 | + $sql = " SELECT layout, description, userid, retired, tags, xml FROM layout "; |
383 | + $sql .= sprintf(" WHERE layoutID = %d ", $this->layoutid); |
384 | + |
385 | + if (!$results = $db->query($sql)) |
386 | + { |
387 | + trigger_error($db->error()); |
388 | + trigger_error(__("Cannot retrieve the Information relating to this layout. The layout may be corrupt."), E_USER_ERROR); |
389 | + } |
390 | + |
391 | + if ($db->num_rows($results) == 0) |
392 | + $this->has_permissions = false; |
393 | + |
394 | + while($aRow = $db->get_row($results)) |
395 | + { |
396 | + $this->layout = Kit::ValidateParam($aRow[0], _STRING); |
397 | + $this->description = Kit::ValidateParam($aRow[1], _STRING); |
398 | + $this->retired = Kit::ValidateParam($aRow[3], _INT); |
399 | + $this->tags = Kit::ValidateParam($aRow[4], _STRING); |
400 | + $this->xml = $aRow[5]; |
401 | + } |
402 | + } |
403 | + } |
404 | + |
405 | + function displayPage() |
406 | + { |
407 | + return false; |
408 | + } |
409 | + |
410 | + function render() |
411 | + { |
412 | + // Render a specific layout in the previewer |
413 | + // layoutid must be provided |
414 | + $output = <<<EOT |
415 | + <!DOCTYPE html> |
416 | + <html> |
417 | + <head> |
418 | + <meta content="text/html; charset=utf-8" http-equiv="Content-Type" /> |
419 | + <title>Preview for Layout $this->layoutid</title> |
420 | + <link rel="stylesheet" type="text/css" href="modules/preview/html-preview.css" /> |
421 | + <script type="text/JavaScript" src="theme/default/libraries/jquery/jquery-1.9.1.js"></script> |
422 | + <script type="text/JavaScript" src="modules/preview/html5Preloader.js"></script> |
423 | + <script type="text/JavaScript" src="modules/preview/html-preview.js"></script> |
424 | + </head> |
425 | + <body onload="dsInit($this->layoutid)"> |
426 | + <div id="player"> |
427 | + <div id="info"></div> |
428 | + <div id="log"></div> |
429 | + <div id="screen"> |
430 | + <div id="splash"> |
431 | + <div id="loader"></div> |
432 | + <div id="loaderCaption"><p>Loading layout...</p></div> |
433 | + </div> |
434 | + <div id="end"><a href="javascript:history.go(0)" style="text-decoration: none; color: #ffffff">Play again?</a></div> |
435 | + </div> |
436 | + |
437 | + </div> |
438 | + </body> |
439 | + </html> |
440 | +EOT; |
441 | + print $output; |
442 | + } |
443 | + |
444 | + function getXlf() |
445 | + { |
446 | + print $this->xml; |
447 | + } |
448 | +} |
449 | +?> |
450 | |
451 | === modified file 'server/modules/flash.module.php' |
452 | --- server/modules/flash.module.php 2014-01-18 09:47:41 +0000 |
453 | +++ server/modules/flash.module.php 2014-02-12 21:14:59 +0000 |
454 | @@ -113,5 +113,16 @@ |
455 | // Client dependant |
456 | return 2; |
457 | } |
458 | + |
459 | + /** |
460 | + * Get Resource |
461 | + */ |
462 | + public function GetResource($displayId = 0) |
463 | + { |
464 | + $this->ReturnFile(); |
465 | + |
466 | + exit(); |
467 | + } |
468 | + |
469 | } |
470 | -?> |
471 | \ No newline at end of file |
472 | +?> |
473 | |
474 | === modified file 'server/modules/image.module.php' |
475 | --- server/modules/image.module.php 2014-01-18 09:47:41 +0000 |
476 | +++ server/modules/image.module.php 2014-02-12 21:14:59 +0000 |
477 | @@ -115,7 +115,7 @@ |
478 | return parent::Preview ($width, $height); |
479 | |
480 | // Show the image - scaled to the aspect ratio of this region (get from GET) |
481 | - return sprintf('<div style="text-align:center;"><img src="index.php?p=module&q=GetImage&id=%d&width=%d&height=%d&dynamic" /></div>', $this->mediaid, $width, $height); |
482 | + return sprintf('<div style="text-align:center;"><img src="index.php?p=module&mod=image&q=Exec&method=GetResource&mediaid=%d&width=%d&height=%d&dynamic=true" /></div>', $this->mediaid, $width, $height); |
483 | } |
484 | |
485 | public function HoverPreview() |
486 | @@ -123,10 +123,71 @@ |
487 | // Default Hover window contains a thumbnail, media type and duration |
488 | $output = parent::HoverPreview(); |
489 | $output .= '<div class="hoverPreview">'; |
490 | - $output .= ' <img src="index.php?p=module&q=GetImage&id=' . $this->mediaid . '&width=200&height=200&dynamic=true" alt="Hover Preview">'; |
491 | + $output .= ' <img src="index.php?p=module&mod=image&q=Exec&method=GetResource&mediaid=' . $this->mediaid . '&width=200&height=200&dynamic=true" alt="Hover Preview">'; |
492 | $output .= '</div>'; |
493 | |
494 | return $output; |
495 | } |
496 | + |
497 | + /** |
498 | + * Get Resource |
499 | + */ |
500 | + public function GetResource($displayId = 0) |
501 | + { |
502 | + $proportional = Kit::GetParam('proportional', _GET, _BOOL, true); |
503 | + $thumb = Kit::GetParam('thumb', _GET, _BOOL, false); |
504 | + $dynamic = isset($_REQUEST['dynamic']); |
505 | + $file = $this->storedAs; |
506 | + |
507 | + //File upload directory.. get this from the settings object |
508 | + $library = Config::GetSetting("LIBRARY_LOCATION"); |
509 | + $fileName = $library . $file; |
510 | + |
511 | + // If we are a thumb request then output the cached thumbnail |
512 | + if ($thumb) |
513 | + $fileName = $library . 'tn_' . $file; |
514 | + |
515 | + // If the thumbnail doesnt exist then create one |
516 | + if (!file_exists($fileName)) |
517 | + { |
518 | + Debug::LogEntry('audit', 'File doesnt exist, creating a thumbnail for ' . $fileName); |
519 | + |
520 | + if (!$info = getimagesize($library . $file)) |
521 | + die($library . $file . ' is not an image'); |
522 | + |
523 | + ResizeImage($library . $file, $fileName, 80, 80, $proportional, 'file'); |
524 | + } |
525 | + |
526 | + // Get the info for this new temporary file |
527 | + if (!$info = getimagesize($fileName)) |
528 | + { |
529 | + echo $fileName . ' is not an image'; |
530 | + exit; |
531 | + } |
532 | + |
533 | + if ($dynamic && $info[2]) |
534 | + { |
535 | + $width = Kit::GetParam('width', _GET, _INT); |
536 | + $height = Kit::GetParam('height', _GET, _INT); |
537 | + |
538 | + // dynamically create an image of the correct size - used for previews |
539 | + ResizeImage($fileName, '', $width, $height, $proportional, 'browser'); |
540 | + |
541 | + exit; |
542 | + } |
543 | + |
544 | + if (!file_exists($fileName)) |
545 | + { |
546 | + //not sure |
547 | + Debug::LogEntry('audit', "Cant find: $uid", 'module', 'GetResource'); |
548 | + |
549 | + $fileName = 'theme/default/img/forms/filenotfound.png'; |
550 | + } |
551 | + |
552 | + $this->ReturnFile($fileName); |
553 | + |
554 | + exit(); |
555 | + |
556 | + } |
557 | } |
558 | -?> |
559 | \ No newline at end of file |
560 | +?> |
561 | |
562 | === added file 'server/modules/preview/html-preview.css' |
563 | --- server/modules/preview/html-preview.css 1970-01-01 00:00:00 +0000 |
564 | +++ server/modules/preview/html-preview.css 2014-02-12 21:14:59 +0000 |
565 | @@ -0,0 +1,92 @@ |
566 | +/* Make the player fill the screen */ |
567 | +html, body { |
568 | + height: 100%; |
569 | + margin: 0; |
570 | + padding: 0; |
571 | + /* cursor: none; */ |
572 | +} |
573 | + |
574 | +div { |
575 | + margin: 0; |
576 | + padding: 0; |
577 | +} |
578 | + |
579 | +/* Make the screen div fill the player */ |
580 | +div#player { |
581 | + height: 100%; |
582 | + z-index: 1; |
583 | + background-color: #000000; |
584 | +} |
585 | + |
586 | +div#screen { |
587 | + height: 100%; |
588 | + z-index: 1; |
589 | +} |
590 | + |
591 | +/* Style the Splash Screen */ |
592 | +div#splash { |
593 | + height: 100%; |
594 | + background:#000000 url('../../theme/default/img/xibologo.png') no-repeat center center; |
595 | + background-size: 50%; |
596 | +} |
597 | + |
598 | +div#loader { |
599 | + height: 19px; |
600 | + width: 220px; |
601 | + position: relative; |
602 | + margin:0 auto; |
603 | + top: 80%; |
604 | + background:#000000 url('loader.gif') no-repeat center center; |
605 | + background-size: 100%; |
606 | +} |
607 | + |
608 | +div#loaderCaption p { |
609 | + position: absolute; |
610 | + font-family: sans-serif; |
611 | + color: #ffffff; |
612 | + text-align:center; |
613 | + top: 85%; |
614 | + width: 100%; |
615 | +} |
616 | + |
617 | +div#log { |
618 | + height: 20px; |
619 | + background:#ffffff; |
620 | + position:absolute; |
621 | + bottom:0; |
622 | + width:100%; |
623 | + font-family: sans-serif; |
624 | + opacity:0.4; |
625 | + z-index: 100; |
626 | +} |
627 | + |
628 | +div#info { |
629 | + position: absolute; |
630 | + height: 400px; |
631 | + width: 500px; |
632 | + background:#ffffff; |
633 | + font-family: sans-serif; |
634 | + opacity:0.6; |
635 | + margin:0 auto; |
636 | + z-index: 100; |
637 | +} |
638 | + |
639 | +div#end { |
640 | + position: absolute; |
641 | + height: 100%; |
642 | + width: 100%; |
643 | + background:#000000; |
644 | + font-family: sans-serif; |
645 | + color:#ffffff; |
646 | + font-size: 300%; |
647 | + margin:0 auto; |
648 | + z-index: 100; |
649 | + text-align: center; |
650 | + vertical-align: middle; |
651 | + line-height: 400px; |
652 | +} |
653 | + |
654 | +video { |
655 | + width: 100%; |
656 | + height: 100%; |
657 | +} |
658 | |
659 | === added file 'server/modules/preview/html-preview.js' |
660 | --- server/modules/preview/html-preview.js 1970-01-01 00:00:00 +0000 |
661 | +++ server/modules/preview/html-preview.js 2014-02-12 21:14:59 +0000 |
662 | @@ -0,0 +1,499 @@ |
663 | +/* |
664 | + * Xibo - Digital Signage - http://www.xibo.org.uk |
665 | + * Copyright (C) 2014 Alex Harrington |
666 | + * |
667 | + * This file is part of Xibo. |
668 | + * |
669 | + * Xibo is free software: you can redistribute it and/or modify |
670 | + * it under the terms of the GNU Affero General Public License as published by |
671 | + * the Free Software Foundation, either version 3 of the License, or |
672 | + * any later version. |
673 | + * |
674 | + * Xibo is distributed in the hope that it will be useful, |
675 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
676 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
677 | + * GNU Affero General Public License for more details. |
678 | + * |
679 | + * You should have received a copy of the GNU Affero General Public License |
680 | + * along with Xibo. If not, see <http://www.gnu.org/licenses/>. |
681 | + */ |
682 | + |
683 | +/* Int: Current logging level */ |
684 | +var LOG_LEVEL; |
685 | + |
686 | +/* String: Client Version */ |
687 | +var VERSION = "1.6.0"; |
688 | + |
689 | +/* Int: Counter to ensure unique IDs */ |
690 | +var ID_COUNTER = 0; |
691 | + |
692 | +var PRELOAD; |
693 | + |
694 | +function dsInit(layoutid) { |
695 | + LOG_LEVEL = 10; |
696 | + |
697 | + /* Hide the info and log divs */ |
698 | + $("#log").css("display", "none"); |
699 | + $("#info").css("display", "none"); |
700 | + $("#end").css("display", "none"); |
701 | + |
702 | + /* Setup a keypress handler for local commands */ |
703 | + document.onkeypress = keyHandler; |
704 | + |
705 | + playLog(0, "info", "Xibo HTML Preview v" + VERSION + " Starting Up", true); |
706 | + |
707 | + PRELOAD = html5Preloader(); |
708 | + runningLayout = new layout(layoutid); |
709 | +} |
710 | + |
711 | +/* Generate a unique ID for region DIVs, media nodes etc */ |
712 | +function nextId() { |
713 | + if (ID_COUNTER > 500) { |
714 | + ID_COUNTER = 0; |
715 | + } |
716 | + |
717 | + ID_COUNTER = ID_COUNTER + 1; |
718 | + return ID_COUNTER; |
719 | +} |
720 | + |
721 | +/* OnScreen Log */ |
722 | +function playLog(logLevel, logClass, logMessage, logToScreen) { |
723 | + if (logLevel <= LOG_LEVEL) |
724 | + { |
725 | + var msg = timestamp() + " " + logClass.toUpperCase() + ": " + logMessage; |
726 | + console.log(msg); |
727 | + |
728 | + if (logToScreen) { |
729 | + document.getElementById("log").innerHTML = msg; |
730 | + } |
731 | + } |
732 | +} |
733 | + |
734 | +/* Timestamp Function for Logs */ |
735 | +function timestamp() { |
736 | + var str = ""; |
737 | + |
738 | + var currentTime = new Date() |
739 | + var day = currentTime.getDate() |
740 | + var month = currentTime.getMonth() + 1 |
741 | + var year = currentTime.getFullYear() |
742 | + var hours = currentTime.getHours() |
743 | + var minutes = currentTime.getMinutes() |
744 | + var seconds = currentTime.getSeconds() |
745 | + |
746 | + if (minutes < 10) { |
747 | + minutes = "0" + minutes |
748 | + } |
749 | + if (seconds < 10) { |
750 | + seconds = "0" + seconds |
751 | + } |
752 | + str += day + "/" + month + "/" + year + " "; |
753 | + str += hours + ":" + minutes + ":" + seconds; |
754 | + return str; |
755 | +} |
756 | + |
757 | +/* Function to handle key presses */ |
758 | +function keyHandler(event) { |
759 | + var chCode = ('charCode' in event) ? event.charCode : event.keyCode; |
760 | + var letter = String.fromCharCode(chCode); |
761 | + |
762 | + if (letter == 'l') { |
763 | + if ($("#log").css("display") == 'none') { |
764 | + $("#log").css("display", "block"); |
765 | + } |
766 | + else { |
767 | + $("#log").css("display", "none"); |
768 | + } |
769 | + } |
770 | + else if (letter == 'i') { |
771 | + if ($("#info").css("display") == 'none') { |
772 | + /* Position the info div */ |
773 | + sw = $("#screen").width(); |
774 | + sh = $("#screen").height(); |
775 | + |
776 | + x = Math.round((sw - 500) / 2); |
777 | + y = Math.round((sh - 400) / 2); |
778 | + |
779 | + if (x > 0) { |
780 | + $("#info").css("left", x); |
781 | + } |
782 | + |
783 | + if (y > 0) { |
784 | + $("#info").css("top", y); |
785 | + } |
786 | + |
787 | + /* Make info div visible */ |
788 | + $("#info").css("display", "block"); |
789 | + } |
790 | + else { |
791 | + $("#info").css("display", "none"); |
792 | + } |
793 | + } |
794 | +} |
795 | + |
796 | +function layout(id) { |
797 | + /* Layout Object */ |
798 | + /* Parses a layout and when run runs it in containerName */ |
799 | + |
800 | + var self = this; |
801 | + |
802 | + self.parseXlf = function(data) { |
803 | + playLog(10, "debug", "Parsing Layout " + self.id, false); |
804 | + self.containerName = "L" + self.id + "-" + nextId(); |
805 | + |
806 | + /* Create a hidden div to show the layout in */ |
807 | + $("#screen").append('<div id="' + self.containerName + '"></div>'); |
808 | + $("#" + self.containerName).css("display", "none"); |
809 | + $("#" + self.containerName).css("outline", "red solid thin"); |
810 | + |
811 | + /* Calculate the screen size */ |
812 | + self.sw = $("#screen").width(); |
813 | + self.sh = $("#screen").height(); |
814 | + playLog(7, "debug", "Screen is (" + self.sw + "x" + self.sh + ") pixels"); |
815 | + |
816 | + /* Find the Layout node in the XLF */ |
817 | + self.layoutNode = data; |
818 | + |
819 | + /* Get Layout Size */ |
820 | + self.xw = $(self.layoutNode).filter(":first").attr('width'); |
821 | + self.xh = $(self.layoutNode).filter(":first").attr('height'); |
822 | + playLog(7, "debug", "Layout is (" + self.xw + "x" + self.xh + ") pixels"); |
823 | + |
824 | + /* Calculate Scale Factor */ |
825 | + self.scaleFactor = Math.min((self.sw/self.xw), (self.sh/self.xh)); |
826 | + self.sWidth = Math.round(self.xw * self.scaleFactor); |
827 | + self.sHeight = Math.round(self.xh * self.scaleFactor); |
828 | + self.offsetX = Math.abs(self.sw - self.sWidth) / 2; |
829 | + self.offsetY = Math.abs(self.sh - self.sHeight) / 2; |
830 | + playLog(7, "debug", "Scale Factor is " + self.scaleFactor); |
831 | + playLog(7, "debug", "Render will be (" + self.sWidth + "x" + self.sHeight + ") pixels"); |
832 | + playLog(7, "debug", "Offset will be (" + self.offsetX + "," + self.offsetY + ") pixels"); |
833 | + |
834 | + /* Scale the Layout Container */ |
835 | + $("#" + self.containerName).css("width", self.sWidth + "px"); |
836 | + $("#" + self.containerName).css("height", self.sHeight + "px"); |
837 | + $("#" + self.containerName).css("position", "absolute"); |
838 | + $("#" + self.containerName).css("left", self.offsetX + "px"); |
839 | + $("#" + self.containerName).css("top", self.offsetY + "px"); |
840 | + |
841 | + /* Set the layout background */ |
842 | + self.bgColour = $(self.layoutNode).filter(":first").attr('bgcolor'); |
843 | + self.bgImage = $(self.layoutNode).filter(":first").attr('background'); |
844 | + |
845 | + $("#" + self.containerName).css("background-color", self.bgColour); |
846 | + |
847 | + if (!(self.bgImage == "" || self.bgImage == undefined)) { |
848 | + /* Extract the image ID from the filename */ |
849 | + self.bgId = self.bgImage.substring(0, self.bgImage.indexOf('.')); |
850 | + |
851 | + PRELOAD.addFiles("index.php?p=module&mod=image&q=Exec&method=GetResource&mediaid=" + self.bgId + "&width=" + self.sWidth + "&height=" + self.sHeight + "&dynamic&proportional=0"); |
852 | + $("#" + self.containerName).css("background", "url('index.php?p=module&mod=image&q=Exec&method=GetResource&mediaid=" + self.bgId + "&width=" + self.sWidth + "&height=" + self.sHeight + "&dynamic&proportional=0')"); |
853 | + $("#" + self.containerName).css("background-repeat", "no-repeat"); |
854 | + $("#" + self.containerName).css("background-size", self.sWidth + "px " + self.sHeight + "px"); |
855 | + $("#" + self.containerName).css("background-position", "0px 0px"); |
856 | + } |
857 | + |
858 | + $(self.layoutNode).find("region").each(function() { playLog(4, "debug", "Creating region " + $(this).attr('id'), false); |
859 | + self.regionObjects.push(new region(self, $(this).attr('id'), this)); |
860 | + }); |
861 | + playLog(4, "debug", "Layout " + self.id + " has " + self.regionObjects.length + " regions"); |
862 | + self.ready = true; |
863 | + PRELOAD.on('finish', self.run); |
864 | + } |
865 | + |
866 | + self.run = function() { |
867 | + playLog(4, "debug", "Running Layout ID " + self.id, false); |
868 | + if (self.ready) { |
869 | + $("#" + self.containerName).css("display", "block"); |
870 | + $("#splash").css("display", "none"); |
871 | + for (var i = 0; i < self.regionObjects.length; i++) { |
872 | + playLog(4, "debug", "Running region " + self.regionObjects[i].id, false); |
873 | + self.regionObjects[i].run(); |
874 | + } |
875 | + } |
876 | + else { |
877 | + playLog(4, "error", "Attempted to run Layout ID " + self.id + " before it was ready.", false); |
878 | + } |
879 | + } |
880 | + |
881 | + self.end = function() { |
882 | + /* Ask the layout to gracefully stop running now */ |
883 | + for (var i = 0; i < self.regionObjects.length; i++) { |
884 | + self.regionObjects[i].end(); |
885 | + } |
886 | + } |
887 | + |
888 | + self.destroy = function() { |
889 | + /* Forcibly remove the layout and destroy this object |
890 | + Layout Object may not be reused after this */ |
891 | + } |
892 | + |
893 | + self.regionExpired = function() { |
894 | + /* One of the regions on the layout expired |
895 | + Check if all the regions have expired, and if they did |
896 | + end the layout */ |
897 | + playLog(5, "debug", "A region expired. Checking if all regions have expired.", false); |
898 | + |
899 | + self.allExpired = true; |
900 | + |
901 | + for (var i = 0; i < self.regionObjects.length; i++) { |
902 | + playLog(4, "debug", "Region " + self.regionObjects[i].id + ": " + self.regionObjects[i].complete, false); |
903 | + if (! self.regionObjects[i].complete) { |
904 | + self.allExpired = false; |
905 | + } |
906 | + } |
907 | + |
908 | + if (self.allExpired) { |
909 | + playLog(4, "debug", "All regions have expired", false); |
910 | + self.end(); |
911 | + } |
912 | + } |
913 | + |
914 | + self.regionEnded = function() { |
915 | + /* One of the regions completed it's exit transition |
916 | + Check al the regions have completed exit transitions. |
917 | + If they did, bring on the next layout */ |
918 | + |
919 | + playLog(5, "debug", "A region ended. Checking if all regions have ended.", false); |
920 | + |
921 | + self.allEnded = true; |
922 | + |
923 | + for (var i = 0; i < self.regionObjects.length; i++) { |
924 | + playLog(4, "debug", "Region " + self.regionObjects[i].id + ": " + self.regionObjects[i].ended, false); |
925 | + if (! self.regionObjects[i].ended) { |
926 | + self.allEnded = false; |
927 | + } |
928 | + } |
929 | + |
930 | + if (self.allEnded) { |
931 | + playLog(4, "debug", "All regions have ended", false); |
932 | + $("#end").css("display", "block"); |
933 | + $("#" + self.containerName).remove(); |
934 | + } |
935 | + |
936 | + } |
937 | + |
938 | + self.ready = false; |
939 | + self.id = id; |
940 | + self.regionObjects = new Array(); |
941 | + |
942 | + playLog(3, "debug", "Loading Layout " + self.id , true); |
943 | + |
944 | + $.get('index.php', {p: 'preview', q: 'getXlf', layoutid: self.id, ajax: 'true'}, self.parseXlf); |
945 | +} |
946 | + |
947 | +function region(parent, id, xml) { |
948 | + var self = this; |
949 | + self.layout = parent; |
950 | + self.id = id; |
951 | + self.xml = xml; |
952 | + self.mediaObjects = new Array(); |
953 | + self.currentMedia = -1; |
954 | + self.complete = false; |
955 | + self.containerName = "R-" + self.id + "-" + nextId(); |
956 | + self.ending = false; |
957 | + self.ended = false; |
958 | + self.oneMedia = false; |
959 | + self.oldMedia = undefined; |
960 | + self.curMedia = undefined; |
961 | + |
962 | + self.finished = function() { |
963 | + self.complete = true; |
964 | + self.layout.regionExpired() |
965 | + } |
966 | + |
967 | + self.exitTransition = function() { |
968 | + /* TODO: Actually implement region exit transitions */ |
969 | + $("#" + self.containerName).css("display", "none"); |
970 | + self.exitTransitionComplete(); |
971 | + } |
972 | + |
973 | + self.end = function() { |
974 | + self.ending = true; |
975 | + /* The Layout has finished running */ |
976 | + /* Do any region exit transition then clean up */ |
977 | + self.exitTransition(); |
978 | + } |
979 | + |
980 | + self.exitTransitionComplete = function() { |
981 | + self.ended = true; |
982 | + self.layout.regionEnded(); |
983 | + } |
984 | + |
985 | + self.transitionNodes = function(oldMedia, newMedia) { |
986 | + /* TODO: Actually support the transition */ |
987 | + |
988 | + if (oldMedia == newMedia) { |
989 | + return; |
990 | + } |
991 | + |
992 | + newMedia.run(); |
993 | + |
994 | + if (oldMedia) { |
995 | + $("#" + oldMedia.containerName).css("display", "none"); |
996 | + } |
997 | + |
998 | + $("#" + newMedia.containerName).css("display", "block"); |
999 | + } |
1000 | + |
1001 | + self.nextMedia = function() { |
1002 | + /* The current media has finished running */ |
1003 | + /* Show the next item */ |
1004 | + |
1005 | + if (self.ended) { |
1006 | + return; |
1007 | + } |
1008 | + |
1009 | + if (self.curMedia) { |
1010 | + playLog(8, "debug", "nextMedia -> Old: " + self.curMedia.id); |
1011 | + self.oldMedia = self.curMedia; |
1012 | + } |
1013 | + else { |
1014 | + self.oldMedia = undefined; |
1015 | + } |
1016 | + |
1017 | + self.currentMedia = self.currentMedia + 1; |
1018 | + |
1019 | + if (self.currentMedia >= self.mediaObjects.length) { |
1020 | + self.finished(); |
1021 | + self.currentMedia = 0; |
1022 | + } |
1023 | + |
1024 | + playLog(8, "debug", "nextMedia -> Next up is media " + (self.currentMedia + 1) + " of " + self.mediaObjects.length); |
1025 | + |
1026 | + self.curMedia = self.mediaObjects[self.currentMedia]; |
1027 | + |
1028 | + playLog(8, "debug", "nextMedia -> New: " + self.curMedia.id); |
1029 | + |
1030 | + /* Do the transition */ |
1031 | + self.transitionNodes(self.oldMedia, self.curMedia); |
1032 | + } |
1033 | + |
1034 | + self.run = function() { |
1035 | + self.nextMedia(); |
1036 | + } |
1037 | + |
1038 | + self.sWidth = $(xml).attr("width") * self.layout.scaleFactor; |
1039 | + self.sHeight = $(xml).attr("height") * self.layout.scaleFactor; |
1040 | + self.offsetX = $(xml).attr("left") * self.layout.scaleFactor; |
1041 | + self.offsetY = $(xml).attr("top") * self.layout.scaleFactor; |
1042 | + |
1043 | + $("#" + self.layout.containerName).append('<div id="' + self.containerName + '"></div>'); |
1044 | + |
1045 | + /* Scale the Layout Container */ |
1046 | + $("#" + self.containerName).css("width", self.sWidth + "px"); |
1047 | + $("#" + self.containerName).css("height", self.sHeight + "px"); |
1048 | + $("#" + self.containerName).css("position", "absolute"); |
1049 | + $("#" + self.containerName).css("left", self.offsetX + "px"); |
1050 | + $("#" + self.containerName).css("top", self.offsetY + "px"); |
1051 | + |
1052 | + playLog(4, "debug", "Created region " + self.id, false); |
1053 | + playLog(7, "debug", "Render will be (" + self.sWidth + "x" + self.sHeight + ") pixels"); |
1054 | + playLog(7, "debug", "Offset will be (" + self.offsetX + "," + self.offsetY + ") pixels"); |
1055 | + |
1056 | + $(self.xml).find("media").each(function() { playLog(5, "debug", "Creating media " + $(this).attr('id'), false); |
1057 | + self.mediaObjects.push(new media(self, $(this).attr('id'), this)); |
1058 | + }); |
1059 | + |
1060 | + playLog(4, "debug", "Region " + self.id + " has " + self.mediaObjects.length + " media items"); |
1061 | +} |
1062 | + |
1063 | +function media(parent, id, xml) { |
1064 | + var self = this; |
1065 | + self.region = parent |
1066 | + self.xml = xml |
1067 | + self.id = id |
1068 | + self.containerName = "M-" + self.id + "-" + nextId(); |
1069 | + |
1070 | + self.run = function() { |
1071 | + playLog(5, "debug", "Running media " + self.id + " for " + self.duration + " seconds") |
1072 | + |
1073 | + if (($(self.xml).attr('type') == "video")) { |
1074 | + $("#" + self.containerName + "-vid").get(0).play(); |
1075 | + } |
1076 | + |
1077 | + if (self.duration == 0) { |
1078 | + if (($(self.xml).attr('type') == "video")) { |
1079 | + $("#" + self.containerName + "-vid").bind("ended", self.region.nextMedia); |
1080 | + } |
1081 | + else { |
1082 | + self.duration = 10; |
1083 | + setTimeout(self.region.nextMedia, self.duration * 1000); |
1084 | + } |
1085 | + } |
1086 | + else { |
1087 | + setTimeout(self.region.nextMedia, self.duration * 1000); |
1088 | + } |
1089 | + } |
1090 | + |
1091 | + self.divWidth = self.region.sWidth; |
1092 | + self.divHeight = self.region.sHeight; |
1093 | + |
1094 | + /* Build Media Options */ |
1095 | + self.duration = $(self.xml).attr('duration'); |
1096 | + self.lkid = $(self.xml).attr('lkid'); |
1097 | + self.options = new Array(); |
1098 | + |
1099 | + $(self.xml).find('options').children().each(function() { playLog(9, "debug", "Option " + this.nodeName.toLowerCase() + " -> " + $(this).text(), false); |
1100 | + self.options[this.nodeName.toLowerCase()] = $(this).text(); |
1101 | + }); |
1102 | + |
1103 | + $("#" + self.region.containerName).append('<div id="' + self.containerName + '"></div>'); |
1104 | + |
1105 | + /* Scale the Content Container */ |
1106 | + $("#" + self.containerName).css("display", "none"); |
1107 | + $("#" + self.containerName).css("width", self.divWidth + "px"); |
1108 | + $("#" + self.containerName).css("height", self.divHeight + "px"); |
1109 | + $("#" + self.containerName).css("position", "absolute"); |
1110 | + /* $("#" + self.containerName).css("left", self.offsetX + "px"); |
1111 | + $("#" + self.containerName).css("top", self.offsetY + "px"); */ |
1112 | + |
1113 | + if ($(self.xml).attr('type') == "image") { |
1114 | + var tmpUrl = "index.php?p=module&mod=image&q=Exec&method=GetResource&layoutid=" + self.region.layout.id + "®ionid=" + self.region.id + "&mediaid=" + self.id + "&lkid=" + self.lkid; |
1115 | + PRELOAD.addFiles(tmpUrl); |
1116 | + $("#" + self.containerName).css("background-image", "url('" + tmpUrl + "')"); |
1117 | + } |
1118 | + else if (($(self.xml).attr('type') == "text")) { |
1119 | + $("#" + self.containerName).append('<iframe scrolling="no" id="innerIframe" src="index.php?p=module&mod=text&q=Exec&method=GetResource&raw=true&preview=true&layoutid=' + self.region.layout.id + '®ionid=' + self.region.id + '&mediaid=' + self.id + '&lkid=&width=' + self.divWidth + '&height=' + self.divHeight + '" width="' + self.divWidth + 'px" height="' + self.divHeight + 'px" style="border:0;"></iframe>'); |
1120 | + } |
1121 | + else if (($(self.xml).attr('type') == "ticker")) { |
1122 | + $("#" + self.containerName).append('<iframe scrolling="no" id="innerIframe" src="index.php?p=module&mod=ticker&q=Exec&method=GetResource&raw=true&preview=true&layoutid=' + self.region.layout.id + '®ionid=' + self.region.id + '&mediaid=' + self.id + '&lkid=&width=' + self.divWidth + '&height=' + self.divHeight + '" width="' + self.divWidth + 'px" height="' + self.divHeight + 'px" style="border:0;"></iframe>'); |
1123 | + /* Check if the ticker duration is based on the number of items in the feed */ |
1124 | + if (self.options['durationisperitem'] == '1') { |
1125 | + var regex = new RegExp("<!-- NUMITEMS=(.*?) -->"); |
1126 | + jQuery.ajax({ |
1127 | + url: 'index.php?p=module&mod=ticker&q=Exec&method=GetResource&raw=true&preview=true&layoutid=' + self.region.layout.id + '®ionid=' + self.region.id + '&mediaid=' + self.id + '&lkid=&width=' + self.divWidth + '&height=' + self.divHeight, |
1128 | + success: function(html) { |
1129 | + res = regex.exec(html); |
1130 | + if (res != null) { |
1131 | + /* The ticker is duration per item, so multiply the duration |
1132 | + by the number of items from the feed */ |
1133 | + self.duration = parseInt(self.duration) * parseInt(res[1]); |
1134 | + } |
1135 | + }, |
1136 | + async:false |
1137 | + }); |
1138 | + } |
1139 | + } |
1140 | + else if (($(self.xml).attr('type') == "video")) { |
1141 | + var tmpUrl = "index.php?p=module&mod=video&q=Exec&method=GetResource&layoutid=" + self.region.layout.id + "®ionid=" + self.region.id + "&mediaid=" + self.id + "&lkid=" + self.lkid; |
1142 | + PRELOAD.addFiles(tmpUrl); |
1143 | + $("#" + self.containerName).append('<video id="' + self.containerName + '-vid" preload="auto"><source src="' + tmpUrl + '"></video>'); |
1144 | + } |
1145 | + else if (($(self.xml).attr('type') == "flash")) { |
1146 | + var tmpUrl = "index.php?p=module&mod=flash&q=Exec&method=GetResource&layoutid=" + self.region.layout.id + "®ionid=" + self.region.id + "&mediaid=" + self.id + "&lkid=" + self.lkid; |
1147 | + var embedCode = '<OBJECT classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" WIDTH="100%" HEIGHT="100%" id="Yourfilename" ALIGN="">'; |
1148 | + embedCode = embedCode + '<PARAM NAME=movie VALUE="' + tmpUrl + '"> <PARAM NAME=quality VALUE=high> <param name="wmode" value="transparent"> <EMBED src="' + tmpUrl + '" quality="high" wmode="transparent" WIDTH="100%" HEIGHT="100%" NAME="Yourfilename" ALIGN="" TYPE="application/x-shockwave-flash" PLUGINSPAGE="http://www.macromedia.com/go/getflashplayer"></EMBED> </OBJECT>'; |
1149 | + PRELOAD.addFiles(tmpUrl); |
1150 | + $("#" + self.containerName).append(embedCode); |
1151 | + } |
1152 | + else { |
1153 | + $("#" + self.containerName).css("outline", "red solid thin"); |
1154 | + } |
1155 | + $("#" + self.containerName).css("background-size", "contain"); |
1156 | + $("#" + self.containerName).css("background-repeat", "no-repeat"); |
1157 | + $("#" + self.containerName).css("background-position", "center"); |
1158 | + |
1159 | + playLog(5, "debug", "Created media " + self.id) |
1160 | +} |
1161 | + |
1162 | |
1163 | === added file 'server/modules/preview/html5Preloader.js' |
1164 | --- server/modules/preview/html5Preloader.js 1970-01-01 00:00:00 +0000 |
1165 | +++ server/modules/preview/html5Preloader.js 2014-02-12 21:14:59 +0000 |
1166 | @@ -0,0 +1,448 @@ |
1167 | +var html5Preloader = (function () { |
1168 | + |
1169 | +var XHR = typeof XMLHttpRequest === 'undefined' ? function () { // IE FIX |
1170 | + try { |
1171 | + return new ActiveXObject("Msxml2.XMLHTTP.6.0"); |
1172 | + } catch (err1) {} |
1173 | + try { |
1174 | + return new ActiveXObject("Msxml2.XMLHTTP.3.0"); |
1175 | + } catch (err2) {} |
1176 | + |
1177 | + return null; |
1178 | + } : XMLHttpRequest, |
1179 | + AudioElement = typeof Audio !== 'undefined' ? // IE FIX |
1180 | + function(){ |
1181 | + return new Audio(); |
1182 | + } : |
1183 | + function(){ |
1184 | + return document.createElement('audio'); |
1185 | + }, |
1186 | + VideoElement = typeof Video !== 'undefined' ? // IE FIX |
1187 | + function () { |
1188 | + return new Video(); |
1189 | + } : |
1190 | + function () { |
1191 | + return document.createElement('video'); |
1192 | + }, |
1193 | + ImageElement = function () { |
1194 | + return new Image(); |
1195 | + }, |
1196 | + codecs = { // Chart from jPlayer |
1197 | + oga: { // OGG |
1198 | + codec: 'audio/ogg; codecs="vorbis"', |
1199 | + media: 'audio' |
1200 | + }, |
1201 | + wav: { // PCM |
1202 | + codec: 'audio/wav; codecs="1"', |
1203 | + media: 'audio' |
1204 | + }, |
1205 | + webma: { // WEBM |
1206 | + codec: 'audio/webm; codecs="vorbis"', |
1207 | + media: 'audio' |
1208 | + }, |
1209 | + mp3: { |
1210 | + codec: 'audio/mpeg; codecs="mp3"', |
1211 | + media: 'audio' |
1212 | + }, |
1213 | + m4a: { // AAC / MP4 |
1214 | + codec: 'audio/mp4; codecs="mp4a.40.2"', |
1215 | + media: 'audio' |
1216 | + }, |
1217 | + ogv: { // OGG |
1218 | + codec: 'video/ogg; codecs="theora, vorbis"', |
1219 | + media: 'video' |
1220 | + }, |
1221 | + webmv: { // WEBM |
1222 | + codec: 'video/webm; codecs="vorbis, vp8"', |
1223 | + media: 'video' |
1224 | + }, |
1225 | + m4v: { // H.264 / MP4 |
1226 | + codec: 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"', |
1227 | + media: 'video' |
1228 | + } |
1229 | + }, |
1230 | + support = { |
1231 | + imageTypes: ['jpg', 'png', 'jpeg', 'tiff', 'gif'] |
1232 | + }, |
1233 | + ID_PREFIX = 'FILE@'; |
1234 | +/* :) may fail sometimes, but these are the most common cases */ |
1235 | +codecs.ogg = codecs.oga; |
1236 | +codecs.mp4 = codecs.m4v; |
1237 | +codecs.webm = codecs.webmv; |
1238 | + |
1239 | +function isIn (needle, haystack) { |
1240 | + for (var i=0; i<haystack.length; i++) { |
1241 | + if (haystack[i] === needle) { |
1242 | + return true; |
1243 | + } |
1244 | + } |
1245 | + |
1246 | + return false; |
1247 | +} |
1248 | + |
1249 | +function map (arr, callback) { |
1250 | + if (arr.map) { |
1251 | + return arr.map(callback); |
1252 | + } |
1253 | + |
1254 | + var r = [], |
1255 | + i; |
1256 | + for (i=0; i<arr.length; i++) { |
1257 | + r.push(callback(arr[i])); |
1258 | + } |
1259 | + |
1260 | + return r; |
1261 | +} |
1262 | + |
1263 | +function bind (func, self) { |
1264 | + return func.bind ? func.bind(self) : function () { |
1265 | + return func.apply(self, arguments); |
1266 | + }; |
1267 | +} |
1268 | + |
1269 | +function delay (callback) { |
1270 | + var args = [].slice.call(arguments, 1); |
1271 | + setTimeout(function () { |
1272 | + callback.apply(this, args); |
1273 | + }, 0); |
1274 | +} |
1275 | + |
1276 | +function EventEmitter () { |
1277 | + var k; |
1278 | + for (k in EventEmitter.prototype) { |
1279 | + if (EventEmitter.prototype.hasOwnProperty(k)) { |
1280 | + this[k] = EventEmitter.prototype[k]; |
1281 | + } |
1282 | + } |
1283 | + this._listeners = {}; |
1284 | +}; |
1285 | + |
1286 | +EventEmitter.prototype = { |
1287 | + _listeners: null, |
1288 | + |
1289 | + emit: function (name, args) { |
1290 | + args = args || []; |
1291 | + if (this._listeners[name]) { |
1292 | + for (var i=0; i<this._listeners[name].length; i++) { |
1293 | + this._listeners[name][i].apply(this, args); |
1294 | + } |
1295 | + } |
1296 | + return this; |
1297 | + }, |
1298 | + |
1299 | + on: function (name, listener) { |
1300 | + this._listeners[name] = this._listeners[name] || []; |
1301 | + this._listeners[name].push(listener); |
1302 | + return this; |
1303 | + }, |
1304 | + |
1305 | + off: function (name, listener) { |
1306 | + if (this._listeners[name]) { |
1307 | + if (!listener) { |
1308 | + delete this._listeners[name]; |
1309 | + return this; |
1310 | + } |
1311 | + for (var i=0; i<this._listeners[name].length; i++) { |
1312 | + if (this._listeners[name][i] === listener) { |
1313 | + this._listeners[name].splice(i--, 1); |
1314 | + } |
1315 | + } |
1316 | + this._listeners[name].length || delete this._listeners[name]; |
1317 | + } |
1318 | + return this; |
1319 | + }, |
1320 | + |
1321 | + once: function (name, listener) { |
1322 | + function ev () { |
1323 | + this.off(ev); |
1324 | + return listener.apply(this, arguments); |
1325 | + } |
1326 | + |
1327 | + return this.on(name, ev); |
1328 | + } |
1329 | +}; |
1330 | + |
1331 | +function loadFile (file, callback, timeout) { |
1332 | + if (!(this instanceof loadFile)) { |
1333 | + return new loadFile(file, callback, timeout); |
1334 | + } |
1335 | + |
1336 | + var self = this, |
1337 | + alternates = [], |
1338 | + a, b, c, t; |
1339 | + |
1340 | + if (typeof file === 'string') { |
1341 | + a = file.split('*:'); |
1342 | + b = a[ a[1] ? 1 : 0 ].split('||'); |
1343 | + self.id = a[1] ? a[0] : b[0]; |
1344 | + self.alternates = alternates; |
1345 | + |
1346 | + for (a=0; a<b.length; a++) { |
1347 | + c = b[a].split('.'); |
1348 | + c = c[c.length - 1].toLowerCase(); |
1349 | + |
1350 | + t = codecs[c] ? codecs[c].media : isIn(c, support.imageTypes) ? 'image' : 'document'; |
1351 | + |
1352 | + if (codecs[c] && !codecs[c].supported) { |
1353 | + continue; |
1354 | + } |
1355 | + |
1356 | + alternates.push({ |
1357 | + type: t, |
1358 | + path: b[a] |
1359 | + }); |
1360 | + } |
1361 | + |
1362 | + alternates.length || alternates.push({ |
1363 | + type: t, |
1364 | + path: b[a-1] |
1365 | + }); |
1366 | + } else { |
1367 | + delay(callback, TypeError('Invalid path'), self); |
1368 | + return; |
1369 | + } |
1370 | + |
1371 | + function loadNext() { |
1372 | + var file = alternates.shift(), |
1373 | + _timeoutTimer = null; |
1374 | + |
1375 | + if (!file) { |
1376 | + delay(callback, {e: Error('No viable alternatives')}, null); |
1377 | + return; |
1378 | + } |
1379 | + |
1380 | + if (typeof timeout === 'number') { |
1381 | + _timeoutTimer = setTimeout(function() { |
1382 | + delay(callback, {e: Error('Load event not fired within ' + timeout + 'ms')}, self); |
1383 | + }, timeout); |
1384 | + } |
1385 | + |
1386 | + new loadFile[file.type]( |
1387 | + file.path, |
1388 | + function (e, f) { |
1389 | + |
1390 | + _timeoutTimer && clearTimeout(_timeoutTimer); |
1391 | + |
1392 | + self.dom = f && f.dom; |
1393 | + |
1394 | + if (e && self.alternates.length) { |
1395 | + return loadNext(); |
1396 | + } |
1397 | + |
1398 | + callback(e, self); |
1399 | + }); |
1400 | + } |
1401 | + |
1402 | + loadNext(); |
1403 | +} |
1404 | + |
1405 | +function MediaFile (construct) { |
1406 | + return function (filename, callback) { |
1407 | + var self = this, |
1408 | + file = construct(); |
1409 | + |
1410 | + function onready () { |
1411 | + file.onload = file.onerror = null; |
1412 | + file.removeEventListener && file.removeEventListener('canplaythrough', onready, true); |
1413 | + |
1414 | + callback(null, self); |
1415 | + } |
1416 | + |
1417 | + file.addEventListener && file.addEventListener('canplaythrough', onready, true); |
1418 | + file.onload = onready; |
1419 | + file.onerror = function (e) { |
1420 | + callback(e, self); |
1421 | + }; |
1422 | + |
1423 | + self.dom = file; |
1424 | + file.src = filename; |
1425 | + |
1426 | + file.load && file.load(); |
1427 | + }; |
1428 | +} |
1429 | + |
1430 | +loadFile.audio = MediaFile(AudioElement); |
1431 | +loadFile.video = MediaFile(VideoElement); |
1432 | +loadFile.image = MediaFile(ImageElement); |
1433 | + |
1434 | +loadFile.document = function (file, callback) { |
1435 | + var self = this, |
1436 | + parsedUrl = /(\[(!)?(.+)?\])?$/.exec(file), |
1437 | + mimeType = parsedUrl[3], |
1438 | + xhr = self.dom = new XHR(); |
1439 | + |
1440 | + if (!xhr) { |
1441 | + delay(callback, Error('No XHR!'), self); |
1442 | + return; |
1443 | + } |
1444 | + |
1445 | + file = file.substr(0, file.length - parsedUrl[0].length); |
1446 | + file += parsedUrl[2] ? (file.indexOf('?') === -1 ? '?' : '&') + 'fobarz=' + (+new Date) : ''; |
1447 | + |
1448 | + mimeType && xhr.overrideMimeType(mimeType === '@' ? 'text/plain; charset=x-user-defined' : mimeType); |
1449 | + |
1450 | + xhr.onreadystatechange = function () { |
1451 | + if (xhr.readyState !== 4) return; |
1452 | + |
1453 | + try { |
1454 | + self.dom = xhr.responseXML && xhr.responseXML.documentElement ? |
1455 | + xhr.responseXML : |
1456 | + String(xhr.responseText || '') ; |
1457 | + |
1458 | + xhr.status === 200 ? |
1459 | + callback(null, self) : |
1460 | + callback({e: Error('Request failed: ' + xhr.status)}, self) ; |
1461 | + } catch (e) { |
1462 | + callback({e: e}, self); |
1463 | + } |
1464 | + }; |
1465 | + |
1466 | + xhr.onerror = function (e) { |
1467 | + callback(e, self); |
1468 | + }; |
1469 | + |
1470 | + xhr.open('GET', file, true); |
1471 | + xhr.send(); |
1472 | +}; |
1473 | + |
1474 | +(function () { |
1475 | + var dummyAudio = AudioElement(), |
1476 | + dummyVideo = VideoElement(), |
1477 | + i; |
1478 | + |
1479 | + support.audio = !!dummyAudio.canPlayType; |
1480 | + support.video = !!dummyVideo.canPlayType; |
1481 | + |
1482 | + support.audioTypes = []; |
1483 | + support.videoTypes = []; |
1484 | + |
1485 | + for (i in codecs) { |
1486 | + if (codecs.hasOwnProperty(i)) { |
1487 | + if (codecs[i].media === 'video') { |
1488 | + (codecs[i].supported = support.video && |
1489 | + dummyVideo.canPlayType(codecs[i].codec)) && |
1490 | + support.videoTypes.push(i); |
1491 | + } else if (codecs[i].media === 'audio') { |
1492 | + (codecs[i].supported = support.audio && |
1493 | + dummyAudio.canPlayType(codecs[i].codec)) && |
1494 | + support.audioTypes.push(i); |
1495 | + } |
1496 | + } |
1497 | + } |
1498 | +}()); |
1499 | + |
1500 | +if (!support.audio) { |
1501 | + loadFile.audio = function (a, callback) { |
1502 | + delay(callback, Error('<AUDIO> not supported.'), a); |
1503 | + }; |
1504 | +} |
1505 | +if (!support.video) { |
1506 | + loadFile.video = function (a, callback) { |
1507 | + delay(callback, Error('<VIDEO> not supported.'), a); |
1508 | + }; |
1509 | +} |
1510 | + |
1511 | +function html5Preloader () { |
1512 | + var self = this, |
1513 | + args = arguments; |
1514 | + |
1515 | + if (!(self instanceof html5Preloader)) { |
1516 | + self = new html5Preloader(); |
1517 | + args.length && self.loadFiles.apply(self, args); |
1518 | + return self; |
1519 | + } |
1520 | + |
1521 | + self.files = []; |
1522 | + |
1523 | + html5Preloader.EventEmitter.call(self); |
1524 | + |
1525 | + self.loadCallback = bind(self.loadCallback, self); |
1526 | + |
1527 | + args.length && self.loadFiles.apply(self, args); |
1528 | +} |
1529 | + |
1530 | +html5Preloader.prototype = { |
1531 | + active: false, |
1532 | + files: null, |
1533 | + filesLoading: 0, |
1534 | + filesLoaded: 0, |
1535 | + filesLoadedMap: {}, |
1536 | + timeout: null, |
1537 | + |
1538 | + loadCallback: function (e, f) { |
1539 | + |
1540 | + if (!this.filesLoadedMap[f.id]) { |
1541 | + this.filesLoaded++; |
1542 | + this.filesLoadedMap[f.id] = f; |
1543 | + } |
1544 | + |
1545 | + this.emit(e ? 'error' : 'fileloaded', e ? [e, f] : [f]); |
1546 | + |
1547 | + if (this.filesLoading - this.filesLoaded === 0) { |
1548 | + this.active = false; |
1549 | + this.emit('finish'); |
1550 | + this.filesLoading = 0; |
1551 | + this.filesLoaded = 0; |
1552 | + } |
1553 | + }, |
1554 | + |
1555 | + getFile: function (id) { |
1556 | + return typeof id === 'undefined' ? map(this.files, function (f) { |
1557 | + return f.dom; |
1558 | + }) : |
1559 | + typeof id === 'number' ? this.files[id].dom : |
1560 | + typeof id === 'string' ? this.files[ID_PREFIX + id].dom : |
1561 | + null; |
1562 | + }, |
1563 | + |
1564 | + removeFile: function (id) { |
1565 | + var f, i; |
1566 | + switch (typeof id) { |
1567 | + case 'undefined': |
1568 | + this.files = []; |
1569 | + break; |
1570 | + case 'number': |
1571 | + f = this.files[id]; |
1572 | + this.files[ID_PREFIX + f.id] && delete this.files[ID_PREFIX + f.id]; |
1573 | + this.files.splice(id, 1); |
1574 | + break; |
1575 | + case 'string': |
1576 | + f = this.files[ID_PREFIX + id]; |
1577 | + f && delete this.files[ID_PREFIX + id]; |
1578 | + |
1579 | + for (i=0; i<this.files.length; i++) { |
1580 | + this.files[i] === f && this.files.splice(i--, 1); |
1581 | + } |
1582 | + } |
1583 | + }, |
1584 | + |
1585 | + loadFiles: function () { |
1586 | + var files = [].slice.call(arguments), |
1587 | + i, f; |
1588 | + |
1589 | + for (i=0; i<files.length; i++) { |
1590 | + f = html5Preloader.loadFile(files[i], this.loadCallback, this.timeout); |
1591 | + this.files.push(f); |
1592 | + this.files[ID_PREFIX + f.id] = f; |
1593 | + this.filesLoading++; |
1594 | + } |
1595 | + |
1596 | + this.active = this.active || !!this.filesLoading; |
1597 | + }, |
1598 | + |
1599 | + addFiles: function (list) { |
1600 | + return this.loadFiles.apply(this, list instanceof Array ? list : arguments); |
1601 | + }, |
1602 | + |
1603 | + getProgress: function () { |
1604 | + return this.filesLoading ? this.filesLoaded / this.filesLoading : 1.0; |
1605 | + } |
1606 | +}; |
1607 | + |
1608 | +html5Preloader.support = support; |
1609 | +html5Preloader.loadFile = loadFile; |
1610 | +html5Preloader.EventEmitter = EventEmitter; |
1611 | + |
1612 | +return html5Preloader; |
1613 | + |
1614 | +}()); |
1615 | |
1616 | === added file 'server/modules/preview/loader.gif' |
1617 | Binary files server/modules/preview/loader.gif 1970-01-01 00:00:00 +0000 and server/modules/preview/loader.gif 2014-02-12 21:14:59 +0000 differ |
1618 | === modified file 'server/modules/video.module.php' |
1619 | --- server/modules/video.module.php 2014-01-18 09:47:41 +0000 |
1620 | +++ server/modules/video.module.php 2014-02-12 21:14:59 +0000 |
1621 | @@ -108,5 +108,16 @@ |
1622 | { |
1623 | return $this->EditLibraryMedia(); |
1624 | } |
1625 | + |
1626 | + /** |
1627 | + * Get Resource |
1628 | + */ |
1629 | + public function GetResource($displayId = 0) |
1630 | + { |
1631 | + $this->ReturnFile(); |
1632 | + |
1633 | + exit(); |
1634 | + |
1635 | + } |
1636 | } |
1637 | -?> |
1638 | \ No newline at end of file |
1639 | +?> |
1640 | |
1641 | === modified file 'server/theme/default/html/layout_designer.php' |
1642 | --- server/theme/default/html/layout_designer.php 2014-01-18 09:47:41 +0000 |
1643 | +++ server/theme/default/html/layout_designer.php 2014-02-12 21:14:59 +0000 |
1644 | @@ -45,6 +45,7 @@ |
1645 | <li><a class="XiboFormButton" href="<?php echo Theme::Get('layout_form_edit_background_url'); ?>" title="<?php echo Theme::Translate('Background'); ?>"><span><?php echo Theme::Translate('Background'); ?></span></a></li> |
1646 | <li><a class="XiboFormButton" href="<?php echo Theme::Get('layout_form_edit_url'); ?>" title="<?php echo Theme::Translate('Edit the Layout Properties'); ?>"><span><?php echo Theme::Translate('Properties'); ?></span></a></li> |
1647 | <li class="divider"></li> |
1648 | + <li><a href="<?php echo Theme::Get('layout_form_preview_url'); ?>" title="<?php echo Theme::Translate('Preview Layout'); ?>" target="_blank"><span><?php echo Theme::Translate('Preview Layout'); ?></span></a></li> |
1649 | <li><a class="XiboFormButton" href="<?php echo Theme::Get('layout_form_schedulenow_url'); ?>" title="<?php echo Theme::Translate('Schedule Now'); ?>"><span><?php echo Theme::Translate('Schedule Now'); ?></span></a></li> |
1650 | <li><a class="XiboFormButton" href="<?php echo Theme::Get('layout_form_savetemplate_url'); ?>" title="<?php echo Theme::Translate('Save Template'); ?>"><span><?php echo Theme::Translate('Save Template'); ?></span></a></li> |
1651 | </ul> |
1652 | @@ -85,4 +86,4 @@ |
1653 | <div class="XiboData"></div> |
1654 | </div> |
1655 | </div> |
1656 | -</div> |
1657 | \ No newline at end of file |
1658 | +</div> |
1659 | |
1660 | === modified file 'server/theme/default/html/layout_page_grid.php' |
1661 | --- server/theme/default/html/layout_page_grid.php 2014-02-08 14:55:15 +0000 |
1662 | +++ server/theme/default/html/layout_page_grid.php 2014-02-12 21:14:59 +0000 |
1663 | @@ -59,7 +59,7 @@ |
1664 | </button> |
1665 | <ul class="dropdown-menu"> |
1666 | <?php foreach($row['buttons'] as $button) { ?> |
1667 | - <li class="<?php echo (($button['id'] == 'layout_button_design') ? 'XiboRedirectButton' : 'XiboFormButton'); ?>" href="<?php echo $button['url']; ?>"><a tabindex="-1" href="#"><?php echo $button['text']; ?></a></li> |
1668 | + <li class="<?php echo ((($button['id'] == 'layout_button_design') or ($button['id'] == 'layout_button_preview')) ? 'XiboRedirectButton' : 'XiboFormButton'); ?>" href="<?php echo $button['url']; ?>" <?php echo (($button['id'] == 'layout_button_preview') ? ' target="_blank"' : ''); ?> ><a tabindex="-1" href="#"><?php echo $button['text']; ?></a></li> |
1669 | <?php } ?> |
1670 | </ul> |
1671 | </div> |
1672 | @@ -67,4 +67,4 @@ |
1673 | </tr> |
1674 | <?php } ?> |
1675 | </tbody> |
1676 | -</table> |
1677 | \ No newline at end of file |
1678 | +</table> |
1679 | |
1680 | === modified file 'server/theme/default/html/library_page_grid.php' |
1681 | --- server/theme/default/html/library_page_grid.php 2014-02-08 14:55:15 +0000 |
1682 | +++ server/theme/default/html/library_page_grid.php 2014-02-12 21:14:59 +0000 |
1683 | @@ -68,8 +68,18 @@ |
1684 | <span class="icon-tasks"></span> |
1685 | </button> |
1686 | <ul class="dropdown-menu"> |
1687 | - <?php foreach($row['buttons'] as $button) { ?> |
1688 | - <li class="XiboFormButton" href="<?php echo $button['url']; ?>"><a tabindex="-1" href="#"><?php echo $button['text']; ?></a></li> |
1689 | + <?php foreach($row['buttons'] as $button) { |
1690 | + if ($button['id'] == 'content_button_download') { |
1691 | + ?> |
1692 | + <li><a tabindex="-1" href="<?php echo $button['url']; ?>"><?php echo $button['text']; ?></a></li> |
1693 | + <?php |
1694 | + } |
1695 | + else { |
1696 | + ?> |
1697 | + <li class="XiboFormButton" href="<?php echo $button['url']; ?>"><a tabindex="-1" href="#"><?php echo $button['text']; ?></a></li> |
1698 | + <?php |
1699 | + } ?> |
1700 | + |
1701 | <?php } ?> |
1702 | </ul> |
1703 | </div> |
1704 | @@ -77,4 +87,4 @@ |
1705 | </tr> |
1706 | <?php } ?> |
1707 | </tbody> |
1708 | -</table> |
1709 | \ No newline at end of file |
1710 | +</table> |
1711 | |
1712 | === modified file 'server/theme/default/js/xibo-layout-designer.js' |
1713 | --- server/theme/default/js/xibo-layout-designer.js 2014-01-18 09:47:41 +0000 |
1714 | +++ server/theme/default/js/xibo-layout-designer.js 2014-02-12 21:14:59 +0000 |
1715 | @@ -310,5 +310,5 @@ |
1716 | //Want to attach an onchange event to the drop down for the bg-image |
1717 | var id = $('#bg_image').val(); |
1718 | |
1719 | - $('#bg_image_image').attr("src", "index.php?p=module&q=GetImage&id=" + id + "&width=80&height=80&dynamic"); |
1720 | -} |
1721 | \ No newline at end of file |
1722 | + $('#bg_image_image').attr("src", "index.php?p=module&mod=image&q=Exec&method=GetResource&mediaid=" + id + "&width=80&height=80&dynamic"); |
1723 | +} |
You'll need to add your preview page to the pages table and give it an appropriate page group. Have you tested a non-admin user?