diff options
| author | Bharat Mediratta <bharat@menalto.com> | 2011-01-03 20:24:21 -0800 |
|---|---|---|
| committer | Bharat Mediratta <bharat@menalto.com> | 2011-01-03 20:24:21 -0800 |
| commit | 8e21dda195015a3c9420553f874c10d3ebfa5dfa (patch) | |
| tree | b7c2974f018dcf3a2d6396da195b22d93b172689 /modules/organize/views | |
| parent | 21ad2c64ff8add478352a0ee7800d87328594ee0 (diff) | |
Complete rewrite of the organize module in Javascript using the Sencha
JavaScript library. It's got all the functionality from the Flash
version except it doesn't support creating new albums or uploading
photos.
Only tested in Chrome 10.0.x so far.
Diffstat (limited to 'modules/organize/views')
| -rw-r--r-- | modules/organize/views/organize_dialog.html.php | 475 | ||||
| -rw-r--r-- | modules/organize/views/organize_frame.html.php | 23 |
2 files changed, 374 insertions, 124 deletions
diff --git a/modules/organize/views/organize_dialog.html.php b/modules/organize/views/organize_dialog.html.php index 3ea1143d..b2e56a04 100644 --- a/modules/organize/views/organize_dialog.html.php +++ b/modules/organize/views/organize_dialog.html.php @@ -1,144 +1,371 @@ <?php defined("SYSPATH") or die("No direct script access.") ?> -<script type="text/javascript" src="<?= url::file("lib/swfobject.js") ?>"></script> -<style type="text/css" media="screen"> - .g-organize { - padding: 0; - margins: 0; - } - - object { - display: block; - outline: none; - } - - #g-dialog { - padding: 0; +<link rel="stylesheet" type="text/css" href="<?= url::file("modules/organize/vendor/ext/css/ext-all.css") ?>" /> +<link rel="stylesheet" type="text/css" href="<?= url::file("modules/organize/vendor/ext/css/ux-all.css") ?>" /> +<link rel="stylesheet" type="text/css" href="<?= url::file("modules/organize/css/organize.css") ?>" /> +<style type="text/css"> + .g-organize div.thumb-album div.icon { + background-image: url(<?= url::file("modules/organize/vendor/ext/images/default/tree/folder.gif") ?>); } </style> +<script type="text/javascript" src="<?= url::file("modules/organize/vendor/ext/js/ext-base.js") ?>"></script> +<script type="text/javascript" src="<?= url::file("modules/organize/vendor/ext/js/ext-all.js") ?>"></script> <script type="text/javascript"> - $("#g-dialog").bind("dialogclose", function(event, ui) { - // @todo do a call to organize/closing to end the batch - if ($(this).data("reload.location")) { - window.location = $(this).data("reload.location"); - } else { - window.location.reload(); - } - }); + Ext.BLANK_IMAGE_URL = "<?= url::file("modules/organize/vendor/ext/images/default/s.gif") ?>"; + Ext.Ajax.timeout = 1000000; // something really large - function closeOrganizeDialog() { - $("#g-dialog").dialog("close"); - } + Ext.onReady(function() { + /* + * ******************************************************************************** + * Utility functions for loading data and making changes + * ******************************************************************************** + */ + var current_album_id = null; + var load_album_data = function(id) { + Ext.Msg.wait(<?= t("Loading...")->for_js() ?>); + Ext.Ajax.request({ + url: '<?= url::site("organize/album_info/__ID__") ?>'.replace("__ID__", id), + success: function(xhr, opts) { + Ext.Msg.hide(); + var album_info = Ext.util.JSON.decode(xhr.responseText); + var store = new Ext.data.JsonStore({ + autoDestroy: true, + fields: ["id", "thumb_url", "width", "height", "type", "title"], + idProperty: "id", + root: "children", + data: album_info + }); + current_album_id = id; + thumb_data_view.bindStore(store); + sort_column_combobox.setValue(album_info.sort_column); + sort_order_combobox.setValue(album_info.sort_order); + }, + failure: function() { + Ext.Msg.hide(); + Ext.Msg.alert( + <?= t("An error occurred. Consult your system administrator.")->for_js() ?>); + } + }); + }; - function setLocation(url) { - $("#g-dialog").data("reload.location", url); - } + var reload_album_data = function() { + if (current_album_id) { + load_album_data(current_album_id); + } + }; - function setTitle(title) { - $("#ui-dialog-title-g-dialog").text(<?= t("Organize :: ")->for_js() ?> + title); - } + var set_album_sort = function(params) { + Ext.Msg.wait(<?= t("Changing sort...")->for_js() ?>); + params['csrf'] = '<?= access::csrf_token() ?>'; + Ext.Ajax.request({ + url: '<?= url::site("organize/set_sort/__ID__") ?>'.replace("__ID__", current_album_id), + method: "post", + success: function() { + Ext.Msg.hide(); + reload_album_data(); + }, + failure: function() { + Ext.Msg.hide(); + Ext.Msg.alert( + <?= t("An error occurred. Consult your system administrator.")->for_js() ?>); + }, + params: params + }); + } - function getOrganizeStyles() { - return { - color: colorToHex($("#g-organize").css("color")), - backgroundColor: colorToHex($("#g-organize").css("backgroundColor")), - borderColor: colorToHex($("#g-organize").css("borderLeftColor")), - rollOverColor: colorToHex($("#g-organize-hover").css("backgroundColor")), - selectionColor: colorToHex($("#g-organize-active").css("backgroundColor")) - }; - } + /* + * ******************************************************************************** + * JsonStore, DataView and Panel for viewing albums + * ******************************************************************************** + */ + thumb_data_view = new Ext.DataView({ + autoScroll: true, + enableDragDrop: true, + itemSelector: "div.thumb", + listeners: { + "render": function(v) { + v.dragZone = new Ext.dd.DragZone(v.getEl(), { + getDragData: function(e) { + var target = e.getTarget(v.itemSelector, 10); + if (target) { + if (!v.isSelected(target)) { + v.onClick(e); + } + var selected_nodes = v.getSelectedNodes(); + var drag_data = { + nodes: selected_nodes, + repair_xy: Ext.fly(target).getXY() + }; + if (selected_nodes.length == 1) { + drag_data.ddel = target; + } else { + var div = document.createElement("div"); + div.className = "multi-proxy"; + for (var i = 0; i != selected_nodes.length; i++) { + div.appendChild(selected_nodes[i].cloneNode(true)); + if ((i+1) % 3 == 0) { + div.appendChild(document.createElement("br")); + } + } + drag_data.ddel = div; + } + return drag_data; + } + }, + getRepairXY: function() { + return this.dragData.repair_xy; + } + }); - function colorToHex(color) { - // Surprising no one, the color extracted from the css is in a different format - // in IE than it is when extracted from FF or Chrome. FF and Chrome return - // the of "rgb(nn,nn,nn)". Where as IE returns it as #hhhhhh. + v.dropZone = new Ext.dd.DropZone(v.getEl(), { + getTargetFromEvent: function(e) { + return e.getTarget("div.thumb", 10); + }, + onNodeEnter: function(target, dd, e, data) { + Ext.fly(target).addClass("active"); + }, + onNodeOut: function(target, dd, e, data) { + Ext.fly(target).removeClass("active"); + }, + onNodeOver: function(target, dd, e, data) { + return Ext.dd.DropZone.prototype.dropAllowed; + }, + onNodeDrop: function(target, dd, e, data) { + var nodes = data.nodes; + source_ids = []; + for (var i = 0; i != nodes.length; i++) { + source_ids.push(Ext.fly(nodes[i]).getAttribute("rel")); + } + Ext.Msg.wait(<?= t("Rearranging...")->for_js() ?>); + Ext.Ajax.request({ + url: '<?= url::site("organize/move_before") ?>', + method: "post", + success: function() { + Ext.Msg.hide(); + reload_album_data(); + }, + failure: function() { + Ext.Msg.hide(); + Ext.Msg.alert( + <?= t("An error occurred. Consult your system administrator.")->for_js() ?>); + }, + params: { + source_ids: source_ids.join(","), + target_id: Ext.fly(target).getAttribute("rel"), + csrf: '<?= access::csrf_token() ?>' + } + }); + return true; + } + }); + } + }, + loadingText: <?= t("Loading...")->for_js() ?>, + multiSelect: true, + selectedClass: "selected", + tpl: new Ext.XTemplate( + '<tpl for=".">', + '<div class="thumb thumb-{type}" id="thumb-{id}" rel="{id}">', + '<img src="{thumb_url}" width="{width}" height="{height}" title="{title}">', + '<div class="icon"></div>', + '</div>', + '</tpl>') + }); - if (color.indexOf("#") === 0) { - return '0x' + color.substring(1); - } else { - var digits = /(.*?)rgb\((\d+), (\d+), (\d+)\)/.exec(color); + /* + * ******************************************************************************** + * Toolbar with sort column, sort order and a close button. + * ******************************************************************************** + */ + var sort_column_combobox = new Ext.form.ComboBox({ + mode: "local", + editable: false, + allowBlank: false, + forceSelection: true, + triggerAction: "all", + store: new Ext.data.ArrayStore({ + id: 0, + fields: ["key", "value"], + data: [ + <? foreach (album::get_sort_order_options() as $key => $value): ?> + ["<?= $key ?>", <?= $value->for_js() ?>], + <? endforeach ?> + ] + }), + listeners: { + "select": function(combo, record, index) { + set_album_sort({sort_column: record.id}); + } + }, + valueField: "key", + displayField: "value" + }); - var red = parseInt(digits[2]); - var green = parseInt(digits[3]); - var blue = parseInt(digits[4]); + var sort_order_combobox = new Ext.form.ComboBox({ + mode: "local", + editable: false, + allowBlank: false, + forceSelection: true, + triggerAction: "all", + store: new Ext.data.ArrayStore({ + id: 0, + fields: ["key", "value"], + data: [ + ["ASC", <?= t("Ascending")->for_js() ?>], + ["DESC", <?= t("Descending")->for_js() ?>]] + }), + listeners: { + "select": function(combo, record, index) { + set_album_sort({sort_order: record.id}); + } + }, + valueField: "key", + displayField: "value" + }); - var rgb = blue | (green << 8) | (red << 16); - return digits[1] + '0x' + rgb.toString(16); - } - } + var button_panel = new Ext.Panel({ + layout: "hbox", + region: "south", + height: 24, + layoutConfig: { + align: "stretch" + }, + items: [sort_column_combobox, sort_order_combobox, + { + xtype: "spacer", + flex: 4, + }, { + xtype: "button", + flex: 1, + text: <?= t("Close")->for_js() ?>, + listeners: { + "click": function() { + parent.done_organizing(current_album_id); + } + } + }, + ] + }); - function getTextStrings() { - return { - statusText: <?= t("Drag and drop photos to re-order or move between album")->for_js() ?>, - remoteError: - <?= t("Remote server error, please contact your gallery administrator")->for_js() ?>, - addAlbumError: <?= t("The above highlighted fields are invalid")->for_js() ?>, - errorOccurred: <?= t("Remote error ocurred")->for_js() ?>, - addAlbum: <?= t("Add album")->for_js() ?>, - addImages: <?= t("Add photo")->for_js() ?>, - deleteSelected: <?= t("Delete")->for_js() ?>, - uploadedText: <?= t("Uploaded {0}")->for_js() ?>, - removeFileText: <?= t("Remove")->for_js() ?>, - progressLabel: <?= t("Completed image %1 of %2")->for_js() ?>, - uploadLabel: <?= t("Loaded %1 of %2 bytes")->for_js() ?>, - moveTitle: <?= t("Move images")->for_js() ?>, - deleteTitle: <?= t("Delete image")->for_js() ?>, - uploadTitle: <?= t("Upload image")->for_js() ?>, - cancel: <?= t("Cancel")->for_js() ?>, - close: <?= t("Close")->for_js() ?> - }; - } + var album_panel = new Ext.Panel({ + layout: "border", + region: "center", + items: [ + { + xtype: "label", + region: "north", + text: <?= t("Drag and drop photos to re-order or move between albums")->for_js() ?>, + margins: "5 5 5 10", + }, + { + xtype: "panel", + layout: "fit", + region: "center", + items: [thumb_data_view] + }, + button_panel + ] + }); - function getGalleryParameters() { - return { - domain: "<?= $domain ?>", - accessKey: "<?= $access_key ?>", - protocol: "<?= request::protocol() ?>", - fileFilter: "<?= $file_filter ?>", - sortOrder: "<?= $sort_order ?>", - sortFields: "<?= $sort_fields ?>", - albumId: "<?= $album->id ?>", - selectedId: "<?= $selected_id ?>", - restUri: "<?= $rest_uri ?>", - controllerUri: "<?= $controller_uri ?>" - }; - }; + /* + * ******************************************************************************** + * TreeLoader and TreePanel + * ******************************************************************************** + */ + var tree_loader = new Ext.tree.TreeLoader({ + dataUrl: '<?= url::site("organize/tree/{$album->id}") ?>', + nodeParameter: "root_id", + requestMethod: "post", + }); + + var tree_panel = new Ext.tree.TreePanel({ + useArrows: true, + autoScroll: true, + animate: true, + border: false, + containerScroll: true, + enableDD: true, + ddGroup: "organizeDD", + listeners: { + "click": function(node) { + load_album_data(node.id); + }, + "render": function(v) { + v.dropZone = new Ext.dd.DropZone(v.getEl(), { + getTargetFromEvent: function(e) { + return e.getTarget("div.x-tree-node-el", 10); + }, + onNodeDrop: function(target, dd, e, data) { + var nodes = data.nodes; + source_ids = []; + for (var i = 0; i != nodes.length; i++) { + var node = Ext.fly(nodes[i]); + source_ids.push(node.getAttribute("rel")); + } + var target_id = target.getAttribute("ext:tree-node-id"); + Ext.Msg.wait(<?= t("Moving...")->for_js() ?>); + Ext.Ajax.request({ + url: '<?= url::site("organize/reparent") ?>', + method: "post", + success: function() { + Ext.Msg.hide(); + reload_album_data(); + v.getNodeById(target_id).reload(); - // For version detection, set to minimum required Flash Player version, or 0 (or 0.0.0), - // for no version detection. - var swfVersionStr = "<?= $flash_minimum_version = "10.0.0" ?>"; + // If the target node contains the selected node, then the selected + // node just got strafed by the target's reload and no longer exists, + // so we can't reload it. + var selected_node = v.getNodeById(current_album_id); + if (selected_node) { + selected_node.reload(); + } + }, + failure: function() { + Ext.Msg.hide(); + Ext.Msg.alert( + <?= t("An error occurred. Consult your system administrator.")->for_js() ?>); + }, + params: { + source_ids: source_ids.join(","), + target_id: target_id, + csrf: '<?= access::csrf_token() ?>' + } + }); + return true; + } + }) + } + }, + loader: tree_loader, - // To use express install, set to playerProductInstall.swf, otherwise the empty string. - var xiSwfUrlStr = ""; - var flashvars = {}; + region: "west", + width: 150, + split: true, - var size = $.gallery_get_viewport_size(); + root: { + nodeType: "async", + text: "<?= item::root()->title ?>", + draggable: false, + id: "<?= item::root()->id ?>", + expanded: true, + } + }); - var params = {}; - params.quality = "high"; - params.bgcolor = "#ffffff"; - params.allowNetworking = "all"; - params.allowscriptaccess = "sameDomain"; - params.allowfullscreen = "true"; - var attributes = {}; - attributes.id = "Gallery3WebClient"; - attributes.name = "Gallery3WebClient"; - attributes.align = "middle"; - swfobject.embedSWF("<?= $swf_uri ?>", - "flashContent", size.width() - 100, size.height() - 135, - swfVersionStr, xiSwfUrlStr, flashvars, params, attributes); + var first_organize_load = true; + tree_loader.addListener("load", function() { + if (first_organize_load) { + tree_panel.getNodeById(<?= $album->id ?>).select(); + load_album_data(<?= $album->id ?>); + first_organize_load = false; + tree_loader.doPreload = function() { return false; } + } + }); + tree_panel.getRootNode().expand(); + + new Ext.Viewport({ + layout: "border", + cls: "g-organize", + items: [tree_panel, album_panel] + }); + }); </script> -<div id="g-organize" class="g-dialog-panel"> - <!-- The following spans are placeholders so we can load the hover and active styles for the flex component --> - <span id="g-organize-hover" /><span id="g-organize-active" /> - <h1 style="display:none"><?= t("Organize :: %name", array("name" => html::purify($album->title))) ?></h1> - <div id="flashContent"> - <p> - <?= t("Your browser must have Adobe Flash Player version %flash_minimum_version or greater installed to use this feature.", array("flash_minimum_version" => $flash_minimum_version)) ?> - </p> - <a href="http://www.adobe.com/go/getflashplayer"> - <img src="<?= request::protocol() ?>://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" - alt=<?= t("Get Adobe Flash Player")->for_js() ?> /> - </a> - </div> -</div> diff --git a/modules/organize/views/organize_frame.html.php b/modules/organize/views/organize_frame.html.php new file mode 100644 index 00000000..2abea898 --- /dev/null +++ b/modules/organize/views/organize_frame.html.php @@ -0,0 +1,23 @@ +<?php defined("SYSPATH") or die("No direct script access.") ?> +<style> + #g-organize-frame { + border: 0px; + width: 100%; + height: 100%; + } +</style> +<script type="text/javascript"> + var ORGANIZE_TITLE = + <?= t("Organize :: %album_title", array("album_title" => "__TITLE__"))->for_js() ?>; + var done_organizing = function(album_id) { + $("#g-dialog").dialog("close"); + window.location = '<?= url::site("items/__ID__") ?>'.replace("__ID__", album_id); + } + + var set_title = function(title) { + $("#g-dialog").dialog("option", "title", ORGANIZE_TITLE.replace("__TITLE__", title)); + } + set_title("<?= $album->title ?>"); +</script> +<iframe id="g-organize-frame" src="<?= url::site("organize/dialog/{$album->id}") ?>"> +</iframe> |
