/** PAGE EDIT APP **/
// this function should be changed to take an entire SavedProject
// (with pages included) ...
function PageEditApp(_pwd_page_data, _pwd_project_data) {
return {
data: _pwd_page_data,
project: _pwd_project_data,
container: null,
staging: null,
edit_w: null,
edit_j: null,
has_been_edited: false,
init: function() {
var body = document.body;
// page container
this.container = document.createElement('div');
YAHOO.util.Dom.addClass(this.container, 'page-edit-area');
body.appendChild(this.container);
// image staging container
this.staging = document.createElement('div');
YAHOO.util.Dom.addClass(this.staging, 'image-staging');
body.appendChild(this.staging);
// load page image
this.load_page_image();
// set page's project_folder_id
this.data.project_folder_id = this.project.project_folder_id;
},
page_id: function() {
return this.data.page_id;
},
img_work_ratio: function() {
return parseFloat(this.data.img_work_ratio);
},
load_page_image: function() {
// give a visual indication that page is loading
YAHOO.util.Dom.addClass(this.container, 'page-loading');
var loading = this.container.appendChild(loading_el('Please wait, loading page template...'));
// load page image into staging area
var img = document.createElement('img');
img.src = '/pages/working/' + this.page_id() + '.png';
this.staging.appendChild(img);
img.loading = loading; // used in callback
// copy into container once it's loaded
YAHOO.util.Event.addListener(img, 'load',
function(e, page_obj) {
// remove events from page image and set image class
YAHOO.util.Event.purgeElement(this);
YAHOO.util.Dom.addClass(this, 'page-template');
// fix PNG for IE < 7 (function does browser check)
fix_png(this);
// remove loading style and loading message
this.loading.parentNode.removeChild(this.loading);
YAHOO.util.Dom.removeClass(page_obj.container, 'page-loading');
// and finally copy to container
page_obj.container.appendChild(this);
// load the rest of our page elements
page_obj.load_page_windows();
page_obj.load_page_journaling();
},
this // scope (callback references this object)
);
},
load_page_windows: function() {
for (var i in this.data.windows) {
var w = this.data.windows[i];
mixin(w, PageWindowBase);
w.init(this);
//YAHOO.log(to_s(w));
// why, for the love of all that is good, i have to do this
// for firefox, i will never know.
//this.data.windows[i] = null;
//this.data.windows[i] = w;
//this.data.windows[i].init.call(this.data.windows[i], this);
//this.data.windows[i] = w; // WHYYSDIROEIHROIEHJORIJE!!!????
//this.data.windows[i].init(this);
}
},
load_page_journaling: function() {
for (var i in this.data.journaling) {
var j = this.data.journaling[i];
mixin(j, PageJournalingBase);
j.init(this);
}
},
select_for_edit: function(obj) {
this.has_been_edited = true;
// first turn current active window or journaling off (if req'd)
//if (this.edit_j) this.edit_j.editing(false);
if (this.edit_w) this.edit_w.editing(false);
this.edit_j = this.edit_w = null;
// hide the rotation controller
hide('rotation-dial');
// determine if obj is photo window or journaling,
// and activate it
// in case we're coming off of a journaling edit,
// remove 'click here to edit photo' message,
//
for (var i in this.data.windows) {
var w = this.data.windows[i];
// if window not changed, remove message, click handler and change
// cursor to default
if (!(w.is_editable())) {
YAHOO.util.Event.purgeElement(w.drag_handle);
YAHOO.util.Dom.setStyle(w.drag_handle, 'cursor', 'pointer');
// on changed windows, hide help message completely
} else {
}
YAHOO.util.Dom.removeClass(w.help, 'click-to-edit-window');
}
$jq("#page-content-edit-area").css("left", "517px");
$jq(".alternate-cal-layouts").css("left", "517px");
// selected photo
if (typeof obj=='object' && obj.page_window_id) {
this.edit_w = obj;
this.edit_w.editing(true);
show('page-window-controls');
// $("page-content-edit-area").style.left = "620px";
$jq("#page-content-edit-area").css("left", "620px");
$jq(".alternate-cal-layouts").css("left", "620px");
hide_journaling_editor();
// selected journaling
} else if (typeof obj=='object' && obj.page_journaling_id) {
this.edit_j = obj; // active
show_journaling_editor();
hide('page-window-controls'); // hide photo controls
for (var i in this.data.windows) {
var w = this.data.windows[i];
if (1) {
YAHOO.util.Dom.addClass(w.help, 'click-to-edit-window');
show(w.help.id);
YAHOO.util.Dom.setStyle(w.drag_handle, 'cursor', 'pointer');
// add a click handler for unmodified windows
// (modified windows call the select_for_edit() function which does
// something similar)
if (!(w.is_editable())) {
// listener to hide journaling, go into photo mode on
// unchaged windows (changed windows already have handler)
YAHOO.util.Event.addListener(w.drag_handle, 'click',
function() {
this.select_for_edit();
return;
},
this,
true
);
}
}
}
// all off
} else {
hide('page-window-controls');
hide_journaling_editor();
}
},
// pull data out of instance
extract_page_data: function() {
//alert(to_s(this.data.windows[0].transformation));
var js = new Object();
// extracts values from an object
// does not recurse into object or arrays
function obj_values(obj) {
var values = new Object();
for (var i in obj) {
if (typeof(obj[i])!='function' && typeof(obj[i])!='object') {
values[i] = obj[i];
}
}
return values;
}
js = obj_values(this.data);
js.windows = new Array();
js.journaling = new Array();
for (var i in this.data.windows) {
var win = obj_values(this.data.windows[i]);
win.transformation = obj_values(this.data.windows[i].transformation);
js.windows.push(win);
}
for (var i in this.data.journaling) {
var j = obj_values(this.data.journaling[i]);
j.transformation = obj_values(this.data.journaling[i].transformation);
js.journaling.push(j);
}
return (js);
},
// sends page data to server for save
save_page: function(onPageSave_cb) {
// save is in progress
if (this.saving)
return;
var PageSaveReq = {
page: this,
onPageSave_cb: onPageSave_cb,
success: function(obj) {
eval('var response = ' + obj.responseText);
this.page.saving = false;
// update this saved IDs
if (response.success) {
this.page.data.saved_page_id = response.saved_page_id;
this.page.data.saved_project_id = response.saved_project_id;
}
// callback (probably to SavedOptionsPanel)
if (typeof this.onPageSave_cb=='function') {
this.onPageSave_cb(response.success, response);
}
},
failure: function(obj) {
this.page.saving = false;
if (typeof this.onPageSave_cb=='function') {
this.onPageSave_cb(false);
}
},
process_result: function(obj) {
},
start_request: function(page_data_json) {
var query = 'saved_page_data=' + escape(page_data_json);
if (QueryString.save_set) query += '&save_set=1';
if (typeof(QueryString.page_set)!='undefined') query += ('&page_set=' + QueryString.page_set);
YAHOO.util.Connect.asyncRequest('POST', '/php/save_customer_project.php',
{
success: PageSaveReq.success,
failure: PageSaveReq.failure,
scope: PageSaveReq
},
query
);
}
}; // PageSaveReq
var page_data = this.extract_page_data();
var page_data_json = JSON.enc_object(page_data);
this.select_for_edit();
// click click click cLICK CLICK!!!
// prevent multiple "save page" clicks
this.saving = true;
PageSaveReq.start_request(page_data_json);
},
// displays a prompt for page name
// pass true to call save_page() when OK is pressed
prompt_page_name: function(save_page) {
// hide journaling editor (flash+YUI dialogs==bad)
this.select_for_edit();
var buttons = [
// ok
{
text: "OK",
handler: function() {
this.hide();
// set the name
Page_1.data.name = this.getData().page_name;
// and save?
if (save_page)
Page_1.save_page();
}
},
// cancel
{
text: "Cancel",
handler: function() {
this.hide();
}
}
];
var dlg = new YAHOO.widget.Dialog('page_name_prompt',
{
postmethod: 'none',
visible: false,
close: false,
width: '280px',
modal: true,
fixedcenter: true,
zIndex: 50000
}
);
dlg.showEvent.subscribe(
function() {
if (Page_1.data.name)
this.form.page_name.value = Page_1.data.name;
selectTextRange(this.form.page_name, 0, this.form.page_name.value.length);
},
dlg,
true
);
dlg.setHeader("Page Name");
dlg.setBody("Please enter a name for your page:
");
dlg.cfg.queueProperty("buttons", buttons);
dlg.render(document.body);
if (dlg.mask)
dlg.mask.style.zIndex = 49999;
dlg.show();
},
// initializes button for next page (or previous partner page, whatever)
// for now, this information is passed to the function from the outside
// this should probably change to get the information from the instance?
show_edit_other_button: function(other) {
if (other) {
this.partner_btn = document.getElementById("partner-page-container");
var c = document.getElementById("partner-page-inner");
var img = document.createElement("img");
img.src = other.saved_page_id ? "/pages/saved/thumbnails/" + other.saved_page_id + ".jpg?size=65" :
"/pages/thumbnails/" + other.page_id + ".jpg?size=65";
c.appendChild(img);
c.innerHTML += 'Edit
Partner
Page';
YAHOO.util.Dom.removeClass(this.partner_btn, "disabled");
YAHOO.util.Event.addListener(this.partner_btn, 'click',
function() {
SavePagePane.savePrompt(this, false, true);
return;
},
this,
true
);
}
}
// end object
}
};
/** PAGE WINDOW FUNCTIONS **/
var PageWindowBase = {
/* these are here for reference, they aren't actually copied
by the mixin function */
container: null,
drag_handle: null,
img: null,
busy: null,
page: null,
help: null,
dd: null,
dd_target: null,
history: Array(),
future: Array(),
warnings: Array(),
/* functions copied to every window object */
init: function(page_obj) {
this.history = Array();
this.future = Array();
this.warnings = Array();
// parent
this.page = page_obj;
// creates and places container
this.window_container();
this.window_drag_handle();
this.window_help_indicator();
//this.window_busy_indicator();
// drag handle also recieves drag-drops
this.dd_target = new YAHOO.util.DDTarget(this.drag_handle.id, 'photos-group');
// reference html elements back to this object
this.container.prnt = this;
this.drag_handle.prnt = this;
this.help.prnt = this;
// update photo image
this.refresh_image();
this.on_image_refresh = function() {
if (this.is_editable()) {
this.editing(false);
}
}
},
refresh_image: function(dropped_photo) {
var url = this.img_url();
var img = document.createElement('img');
this.set_window_busy(true);
// begin image loading, appending it to staging area
img.src = url + '?ts=' + new Date().getTime(); // because ie7 (6?) doesn't call onload when loading cached url?????????!?!?!?!?!?k12j3kl12j34
this.page.staging.appendChild(img);
// add a loading message to window
img.loading = this.container.appendChild(loading_el('Refreshing...'));
YAHOO.util.Event.addListener(img, 'load',
function(e, scope) {
// strip onload from image
YAHOO.util.Event.purgeElement(this);
// store original size
this.original_w = this.width;
this.original_h = this.height;
scope.img = this; // window ref (shortcut)
img.prnt = scope; // ref to page_window object
// assign random id to image
YAHOO.util.Dom.generateId(img);
// remove message
this.loading.parentNode.removeChild(img.loading);
// (re)--place the image
// if (scope.container.firstChild)
// scope.container.replaceChild(this, scope.container.firstChild);
// else
// scope.container.appendChild(this);
scope.container.innerHTML = '';
scope.container.appendChild(this);
//YAHOO.log('new image: ' + this.src);
//scope.editing.call(scope, false);
if (scope.is_editable()) {
YAHOO.util.Dom.removeClass(this.help, 'drag-here' + scope.css_small.call(scope));
// prevent selection for edit if we're loading a previously
// completed page
//scope.page.select_for_edit(scope);
} else {
// disable drag (only for default photos)
scope.dd = null;
YAHOO.util.Dom.setStyle(scope.drag_handle, 'cursor', 'default');
// prompt to drag photos
YAHOO.util.Dom.addClass(scope.help, 'drag-here' + scope.css_small.call(scope));
}
// fit dropped photos to window
if (dropped_photo) {
scope.no_animation = true;
scope.set_transformation('fit', null, true); // (don't save in history)
scope.no_animation = false;
// show below message ONLY once per window
if (!(scope.page.window_move_message_shown)) {
scope.window_warn('Use your mouse to reposition this photo inside of the window. Use the control panel on the right ' +
'to change photo color, size, etc.', 'helptip1');
scope.page.window_move_message_shown = true; // uncomment to show only once
}
// ...
} else {
scope.no_animation = true;
scope.apply_html_transformations(); // position existing photos at correct location
scope.no_animation = false;
}
scope.set_window_busy(false);
if (typeof scope.on_image_refresh=='function') {
scope.on_image_refresh.call(scope);
}
},
this // (passed as 'scope' to inline function above)
);
},
// activates the current window for drag drop, etc
editing: function(edit) {
YAHOO.log("** EDITING: " + edit);
if (edit) {
// removes active window click handler from drag handle
YAHOO.util.Event.purgeElement(this.drag_handle);
// add DD
YAHOO.util.Dom.removeClass(this.help, 'drag-here' + this.css_small());
hide(this.help);
this.dd = new YAHOO.util.DD(this.img.id);
this.dd.endDrag = this.photo_location_changed;
this.dd.onMouseDown = function() { (this.getEl().prnt.window_warn_close.call(this.getEl().prnt.warnings['helptip1'], null, this.getEl().prnt)) };
this.dd.setOuterHandleElId(this.drag_handle.id);
YAHOO.util.Dom.setStyle(this.drag_handle, 'cursor', 'move');
this.window_warnings_show();
} else {
this.window_warnings_hide();
// unregister drag/drop
if (this.dd)
this.dd.unreg();
YAHOO.util.Event.addListener(this.drag_handle, 'mousedown', function() { this.page.select_for_edit(this); }, this, true);
YAHOO.util.Dom.setStyle(this.drag_handle, 'cursor', 'pointer');
}
},
// (not used)
set_window_busy: function(isbusy) {
return;
var anim_opts = isbusy ? { opacity: { to: 0.5 } } : { opacity: { to: 0 } };
var anim = new YAHOO.util.Anim(this.busy.id, anim_opts, 0.1);
anim.animate();
//YAHOO.log(isbusy);
},
save_history: function() {
if (!(this.img))
return;
var img = this.img;
var history = {
photo_id: this.photo_id,
transformation: clone_object(this.transformation),
img:
{
src: this.img.src,
width: this.img.width,
height: this.img.height,
original_w: this.img.original_w,
original_h: this.img.original_h
}
};
this.history.push( history );
// making history clears redo stack
this.future = Array();
//YAHOO.log("\nSAVE\n" + to_s(this.history[this.history.length-1]));
},
restore_history: function(history) {
if (this.history.length==0)
return;
var hist = history ? history : this.history.pop();
//YAHOO.log("\nRESTORE\n" + to_s(hist));
this.photo_id = hist.photo_id;
this.transformation = clone_object(hist.transformation);
// different photo?
if (this.img.src != hist.img.src) {
this.img.src = hist.img.src;
this.img.width = hist.img.width;
this.img.height = hist.img.height;
this.img.original_w = hist.img.original_w;
this.img.original_h = hist.img.original_h;
}
// resize and move
this.apply_html_transformations();
},
back_to_the_future: function() {
if (this.future.length==0)
return;
var future = this.future.pop();
//YAHOO.log("\nREDO\n" + to_s(future));
this.restore_history(future);
},
// sets transformations
set_transformation: function(key, value, no_save_history) {
// first, save history
if (!(no_save_history))
this.save_history();
var tr = this.transformation;
var refresh = false;
// zoom in/out transform
if (key=='zoom') {
if (!tr.zoom) tr.zoom = 1;
new_zoom = parseFloat(tr.zoom) + parseFloat(value);
if (new_zoom>0) tr.zoom = new_zoom;
}
// calculate zoom so that photo fits window
if (key=='fit') {
var cw = this.width * this.page.img_work_ratio();
var ch = this.height * this.page.img_work_ratio();
var nw = cw;
var nh = nw * (this.img.original_h/this.img.original_w);
if (nh 2) {
this.window_warn('This photo has been resized beyond its original size. Printed photo quality' +
' may be less than optimal.', 'zoomwarning');
} else if (tr.zoom && azoom < 2 && typeof this.warnings['zoomwarning']=='object') {
this.window_warn_close.call(this.warnings['zoomwarning'], null, this);
this.warnings['zoomwarning'] = false;
}
// change to (red) when resized WAY too much
if (typeof(this.warnings['zoomwarning'])=='object' && azoom>=3)
YAHOO.util.Dom.addClass(this.warnings['zoomwarning'].obj, 'redbg');
// else back to (yellow)
else if (typeof(this.warnings['zoomwarning'])=='object')
YAHOO.util.Dom.removeClass(this.warnings['zoomwarning'].obj, 'redbg');
} catch (cold) {
// ...
}
// toggle sepia (turns black & white off)
if (key=='sepia') {
tr.sepia = !(tr.sepia);
tr.bw = false;
refresh = true;
}
// toggle bw (turns sepia off)
if (key=='bw') {
tr.bw = !(tr.bw);
tr.sepia = false;
refresh = true;
}
// toggle flip
if (key=='flip') {
tr.flip = !(tr.flip);
refresh = true;
}
// toggle flop
if (key=='flop') {
tr.flop = !(tr.flop);
refresh = true;
}
// +/- brightness
if (key=='density') {
if (!(tr.density)) tr.density = 0;
var new_density = parseInt(tr.density) + parseInt(value);
if (new_density>100) new_density = 100;
else if (new_density<-100) new_density = -100;
tr.density = new_density;
refresh = true;
}
// rotation
if (key=='rotate') {
tr.rotate = (value>-360 && value<=360) ? value : 0
refresh = true;
}
this.apply_html_transformations();
// photo reload is needed?
if (refresh)
this.refresh_image();
},
apply_html_transformations: function() {
var tr = this.transformation;
var nn = {}; // YAHOO animation config
// size
if (tr.zoom) {
// calculate new sizes
var nw = parseInt(this.img.original_w * tr.zoom);
var nh = parseInt(this.img.original_h * tr.zoom);
// update animation config
nn.width = { to: nw };
nn.height = { to: nh };
}
// photo offset (relative, web sized, in window)
if (!(isNaN(parseInt(tr.web_xoffset)))) {
nn.left = { to: parseInt(tr.web_xoffset) };
}
if (!(isNaN(parseInt(tr.web_yoffset)))) {
nn.top = { to: parseInt(tr.web_yoffset) };
}
// execute
if (this.no_animation) {
if (nn.width && nn.width.to) this.img.width = nn.width.to;
if (nn.height && nn.height.to) this.img.height = nn.height.to;
if (nn.left && nn.left.to) this.img.style.left = nn.left.to + 'px';
if (nn.top && nn.top.to) this.img.style.top = nn.top.to + 'px';
} else {
var yui_anim = new YAHOO.util.Anim(this.img.id, nn, 0.3, YAHOO.util.Easing.easeOut);
yui_anim.animate();
}
},
photo_location_changed: function() {
var img = this.getEl();
var win = img.prnt;
win.save_history();
win.transformation.web_xoffset = parseInt(img.style.left);
win.transformation.web_yoffset = parseInt(img.style.top);
},
// allow to apply filters, move, etc?
is_editable: function() {
return this.photo_id>0;
},
css_small: function() {
return (parseInt(this.container.style.width)<=110 || parseInt(this.container.style.height)<=110) ?
'-small' : '';
},
window_container: function() {
// create container (used to hide image from other page_windows)
this.container = this.window_div();
YAHOO.util.Dom.addClass(this.container, 'page-part-container');
// layer (z-index)
this.container.style.zIndex = this.layer;
this.page.container.appendChild(this.container);
},
window_drag_handle: function() {
// used for dragging around image that's in container
// since container is under the page template and iamge can't
// receive clicks
this.drag_handle = this.window_div();
YAHOO.util.Dom.addClass(this.drag_handle, 'page-window-drag-handle');
// iexplorer needs an element to have a background color in order to receive events?
YAHOO.util.Dom.setStyle(this.drag_handle, 'backgroundColor', 'white');
YAHOO.util.Dom.setStyle(this.drag_handle, 'opacity', 0);
this.page.container.appendChild(this.drag_handle);
},
window_help_indicator: function() {
// shows an overlayed prompt
this.help = this.window_div();
YAHOO.util.Dom.addClass(this.help, 'page-help-indicator');
this.page.container.appendChild(this.help);
},
window_busy_indicator: function() {
// visual indicator that window is being loaded
this.busy = this.window_div();
YAHOO.util.Dom.addClass(this.busy, 'page-window-busy');
YAHOO.util.Dom.setStyle(this.busy, 'opacity', 0);
YAHOO.util.Dom.generateId(this.busy);
this.page.container.appendChild(this.busy);
},
// returns a div element with appropriate
// window size set
window_div: function() {
var el = document.createElement('div');
var s = el.style;
s.position= 'absolute';
s.width = parseInt(this.width * this.page.img_work_ratio()) + 'px';
s.height = parseInt(this.height * this.page.img_work_ratio()) + 'px';
s.top = parseInt(this.ypos * this.page.img_work_ratio()) + 'px';
s.left = parseInt(this.xpos * this.page.img_work_ratio()) + 'px';
// give it a random id
YAHOO.util.Dom.generateId(el);
return el;
},
// displays a warning message
window_warn: function(message, warning_id, additional_class) {
// this message is being displayed, or has already been displayed
// do not display again
if (this.warnings[warning_id] || !(warning_id))
return;
var wp = document.createElement('p'); // container
var sw = document.createElement('span'); // warning text
var sc = document.createElement('span'); // dismiss message text
var wc = document.createElement('div'); // close trigger (recieves click to close)
YAHOO.util.Dom.generateId(wp);
// position at top of window
YAHOO.util.Dom.addClass(wp,'page-window-warning' + (this.css_small() ? ' small' : ''));
if (additional_class)
YAHOO.util.Dom.addClass(wp, additional_class);
wp.style.width = parseInt(this.width * this.page.img_work_ratio()) + 'px';
wp.style.top = parseInt(this.ypos * this.page.img_work_ratio()) + 'px';
wp.style.left = parseInt(this.xpos * this.page.img_work_ratio()) + 'px';
// set message text and close text
sw.innerHTML = message;
YAHOO.util.Dom.addClass(sw, 'message');
sc.innerHTML = 'close';
YAHOO.util.Dom.addClass(sc, 'dismiss');
// append to message
wp.appendChild(sw);
wp.appendChild(sc);
// append to page, fade in
YAHOO.util.Dom.setStyle(wp, 'opacity', 0);
this.page.container.appendChild(wp);
// hack to put resolution resize wanring on bottom
if (warning_id == 'zoomwarning')
wp.style.top = parseInt(wp.style.top) + (parseInt(this.height * this.page.img_work_ratio()) - wp.offsetHeight) + 'px';
var anim_opts = { opacity: { to: 0.85 } };
var anim = new YAHOO.util.Anim(wp.id, anim_opts, 0.3);
anim.animate();
// create the dismiss message trigger (sits on top of drag handler
// so that it can receive mouse clicks
YAHOO.util.Dom.addClass(wc, 'page-window-warning-trigger');
wc.style.top = wp.style.top;
wc.style.left = wp.style.left;
wc.style.width = wp.style.width;
wc.style.height = wp.offsetHeight + 'px';
YAHOO.util.Dom.setStyle(wc, 'backgroundColor', 'white');
YAHOO.util.Dom.setStyle(wc, 'opacity', 0);
YAHOO.util.Dom.setStyle(wc, 'cursor', 'pointer');
// associate close trigger with what it's closing
wc.obj = wp;
YAHOO.util.Event.addListener(wc, 'click', this.window_warn_close, this);
// append close trigger to container
this.page.container.appendChild(wc);
// add to warnings tracker
wc.warning_id = warning_id;
this.warnings[warning_id] = wc;
},
window_warn_close_fast: function(obj) {
if (!obj.obj)
return;
obj.obj.parentNode.removeChild(obj.obj);
obj.parentNode.removeChild(obj);
this.warnings[obj.warning_id] = true;
},
window_warn_close: function(evt, win_obj) {
// make sure that 'this' is an actual warn object
if (!(this.warning_id))
return;
var anim_opts = { opacity: { to: 0 } };
var anim = new YAHOO.util.Anim(this.obj.id, anim_opts, 0.1);
// remove message node from dom
function removeMessage() {
var el = this.getEl();
el.parentNode.removeChild(el);
}
anim.onComplete.subscribe(removeMessage);
anim.animate();
this.parentNode.removeChild(this);
win_obj.warnings[this.warning_id] = true;
},
window_warnings_hide: function() {
for (i in this.warnings) {
if (typeof(this.warnings[i])=='object') {
hide(this.warnings[i]);
hide(this.warnings[i].obj);
}
}
},
window_warnings_show: function() {
for (i in this.warnings) {
if (typeof(this.warnings[i])=='object') {
show(this.warnings[i]);
show(this.warnings[i].obj);
}
}
},
img_url: function() {
// translate the transofrmation to soemthing
// that can be sent in the url
// (key:value;key:value;etc...)
var trans = Array();
for (i in this.transformation) {
switch (i) {
case 'zoom':
case 'web_xoffset':
case 'web_yoffset':
break;
default:
trans.push(i + ":" + this.transformation[i])
}
}
trans = trans.join('%3B');
return this.photo_id ?
'/myphotos/working/' + (trans ? trans : '0') + '/' + this.photo_id + '.jpg' :
'/pages/working/' + this.page.page_id() + '/windows/' + this.page_window_id + '.png';
},
drop_photo: function(photo_id, el_NU, photo_obj) {
// clear all displayed warnings
for (var i in this.warnings) {
if (this.warnings[i] instanceof Object)
this.window_warn_close.call(this.warnings[i], null, this);
}
this.warnings = Array();
// if custom photo is already place, save in history
if (this.photo_id)
this.save_history()
// set photo object
this.photo_obj = photo_obj;
this.photo_id = photo_id;
this.transformation = Array();
if (this.rotate!=0)
this.transformation.rotate = this.rotate;
this.refresh_image(true);
// select dropped photos for editing
// called by refresh_image when image is refreshed (!!)
this.on_image_refresh = function() {
this.editing(true);
this.page.select_for_edit(this);
//YAHOO.log('on_image_refresh');
}
},
toString: function() {
var str = "";
for (i in this.transformation)
str += i + ": " + this.transformation[i] + ", ";
return str;
}
}
var PageJournalingBase = {
container: null, // holds image
img: null, // png text image
prompt: null, // (optional) prompt "click to add text"
transformation: {},
overflow: 0,
init: function(page) {
this.page = page;
// append the "click ehre to edit" prompt
this.set_prompt();
// container for journaling image
this.container = this.window_div();
YAHOO.util.Dom.addClass(this.container, "page-journaling");
this.page.container.appendChild(this.container);
// prompt and container both receive activate clicks
this.attach_click_handler(this.prompt);
this.attach_click_handler(this.container);
this.update_image();
},
nudge: function(amt_x, amt_y, reset) {
if (!(this.has_custom_text()))
return;
if (reset===true) {
this.transformation['web_yoffset'] = 0;
this.transformation['web_xoffset'] = 0;
this.container.style.top = this.ypos * this.page.img_work_ratio() + "px";
this.container.style.left = this.xpos * this.page.img_work_ratio() + "px";
}
var max_move_amt = .33 * 72; // about 1/3 inch?
if (amt_y) var new_y = parseInt(this.container.style.top) + parseInt(amt_y);
if (amt_x) var new_x = parseInt(this.container.style.left) + parseInt(amt_x);
var old_y = parseInt(this.ypos * this.page.img_work_ratio());
var old_x = parseInt(this.xpos * this.page.img_work_ratio());
if (Math.abs(new_y - old_y) < max_move_amt) {
this.container.style.top = new_y + 'px';
this.transformation['web_yoffset'] = new_y - old_y;
}
if (Math.abs(new_x - old_x) < max_move_amt) {
this.container.style.left = new_x + 'px';
this.transformation['web_xoffset'] = new_x - old_x;
}
},
has_custom_text: function() {
return (!(this.custom_text=='' || this.custom_text==null || this.custom_text==false));
},
update_image: function() {
this.loading = loading_el('Refreshing...');
this.container.appendChild(this.loading);
// for some reason, this.transformation is instanceof Array (it's not)
// JSON fails
_transformation_hack = {};
for (var i in this.transformation)
_transformation_hack[i] = this.transformation[i];
if (this.has_custom_text()) {
// YAHOO connect to request generated journaling image
var JournalImgReq = {
journal: this, // reference to selected journaling object
success: function(obj) {
eval("var response = " + obj.responseText);
if (!(response.status)) {
// handle failure
} else {
//var location = '/php/journal_generator.php?location=' + response.location;
var location = '/generated/journal/' + response.location + '.png';
this.journal._update_image.call(this.journal, location);
this.journal.overflow = response.overflow;
if (typeof(overflow_check)=='function')
overflow_check();
}
},
failure: function(obj) {
alert('Failed to get journaling iamge');
},
start_request: function() {
// create request object
var j_obj = {
custom_text: JournalImgReq.journal.custom_text,
line_spacing: JournalImgReq.journal.line_spacing,
padding: JournalImgReq.journal.padding,
transformation: _transformation_hack,
page_journaling_id: JournalImgReq.journal.page_journaling_id,
page_id: JournalImgReq.journal.page.page_id()
};
var j_obj_js = JSON.stringify(j_obj);
YAHOO.util.Connect.asyncRequest('POST', '/php/journal_generator.php',
{
success: JournalImgReq.success,
failure: JournalImgReq.failure,
scope: JournalImgReq
},
'request_data=' + escape(j_obj_js)
);
}
}
JournalImgReq.start_request();
} else if (!(this.default_text)) {
// load blank image ("place text here")
this._update_image("/images/default_text.png");
} else {
// just load default journaling image
this._update_image("/pages/working/" + this.page.page_id() + "/journaling/" + this.page_journaling_id + ".png");
}
},
_update_image: function(image_url) {
var img = document.createElement("img");
img.src = image_url;
// append to staging
this.page.staging.appendChild(img);
// display when loaded
YAHOO.util.Event.addListener(img, "load",
function(evt, scope) {
// remove listeners
YAHOO.util.Event.purgeElement(this);
scope.container.removeChild(scope.loading);
// disable "edit journaling" prompt
if (scope.has_custom_text())
YAHOO.util.Dom.addClass(scope.prompt, 'disabled');
/*if (scope.container.firstChild)
scope.container.replaceChild(this, scope.container.firstChild)
else
scope.container.appendChild(this);*/
scope.container.innerHTML = '';
scope.container.appendChild(this);
scope.img = this;
fix_png(this, 'image'); // alsjkdflakjs32890r5 (sizing method)
scope.adjust_position();
},
// "scope" variable above
this
);
},
// rotated images are larger than the area specified
// adjust positioning in that case
adjust_position: function() {
// $rx = $x + ($w / 2) - ($ow / 2);
// $ry = $y + ($h / 2) - ($oh / 2);
// shortcut
var c = this.container;
var i = c.firstChild;
var cw = parseInt(c.offsetWidth);
var ch = parseInt(c.offsetHeight);
var iw = parseInt(i.offsetWidth);
var ih = parseInt(i.offsetHeight);
i.style.left = parseInt((cw / 2) - (iw / 2)) + 'px';
i.style.top = parseInt((ch / 2) - (ih / 2)) + 'px';
//alert(i.width + " x " + i.height + " vs " + i.offsetWidth + " x " + i.offsetHeight);
//alert(cw + ", " + ch + ", " + iw + ", " + ih);
},
// attaches handler to el for activating editing function
attach_click_handler: function(el) {
YAHOO.util.Event.purgeElement(el);
YAHOO.util.Event.addListener(el, 'click',
function() {
//YAHOO.log("journaling_id: " + this.page_journaling_id);
this.page.select_for_edit(this);
},
this,
true
);
},
window_div: function() {
var dv = document.createElement('div');
YAHOO.util.Dom.generateId(dv);
YAHOO.util.Dom.addClass(dv, 'page-part');
var xoffset = this.transformation.web_xoffset ? parseInt(this.transformation.web_xoffset) : 0;
var yoffset = this.transformation.web_yoffset ? parseInt(this.transformation.web_yoffset) : 0;
//alert(xoffset + ", " + yoffset);
var s = dv.style;
s.position= 'absolute';
s.width = parseInt(this.width * this.page.img_work_ratio()) + 'px';
s.height = parseInt(this.height * this.page.img_work_ratio()) + 'px';
s.top = parseInt(this.ypos * this.page.img_work_ratio() + yoffset) + 'px';
s.left = parseInt(this.xpos * this.page.img_work_ratio() + xoffset) + 'px';
s.cursor = 'pointer';
return dv;
},
// place the "click here to edit text" prompt
// try to palce it so that it does not overlap other
// page parts
set_prompt: function() {
var prompt = document.createElement("img");
prompt.src = "/images/add-text-left_1.png";
YAHOO.util.Dom.addClass(prompt, "page-journaling-prompt");
var s = prompt.style;
s.position= 'absolute';
s.left = parseInt((parseInt(this.width) + parseInt(this.xpos)) * this.page.img_work_ratio()) + 'px';
s.top = parseInt(this.ypos * this.page.img_work_ratio()) - 20 + 'px';
s.width = '110px'; // image width/height hardcoded (for overlap test)
s.height = '43px';
s.cursor = 'pointer';
// (find a quicker way to do this)
YAHOO.log('.........' + (parseInt(prompt.style.left) + parseInt(prompt.style.width)))
if (this.overlaps_others(prompt) || parseInt(prompt.style.left) + parseInt(prompt.style.width)>470) {
var old_prompt = prompt.cloneNode( false);
prompt.src = "/images/add-text-right_1.png";
prompt.style.left = parseInt(parseInt(this.xpos)) * this.page.img_work_ratio() - parseInt(prompt.style.width) + "px";
// if it still overlaps, or sticks off of the edge of they page by
// more than 10 pixels, use old one
//if ((this.overlaps_others(prompt) || parseInt(prompt.style.left)<-10))
// prompt = old_prompt;
}
fix_png(prompt);
this.prompt = prompt;
this.page.container.appendChild(prompt);
// if this journaling has been modified, perm disable prompt
if (this.has_custom_text())
YAHOO.util.Dom.addClass(this.prompt, 'disabled');
},
overlaps_others: function(el) {
var x0 = parseInt(el.style.left)
var y0 = parseInt(el.style.top);
var x1 = parseInt(el.style.width) + x0;
var y1 = parseInt(el.style.height) + y0;
for (var i in this.page.data.windows) {
var o = this.page.data.windows[i].container;
var x2 = parseInt(o.style.left);
var y2 = parseInt(o.style.top);
var x3 = parseInt(o.style.width) + x2;
var y3 = parseInt(o.style.height) + y2;
if (this.overlaps(x0,y0,x1,y1,x2,y2,x3,y3))
return true;
}
return false;
},
// true rectangle (x0, y0, x1, y1) overlaps rectangle (x2, y2, x3, y3)
overlaps: function(x0,y0,x1,y1,x2,y2,x3,y3) {
//YAHOO.log(x0 + " " + y0 + " " + x1 + " " + y1 + " " + x2 + " " + y2 + " " + x3 + " " + y3);
return ( (!( ((x0)<(x2) && (x1)<(x2))
|| ((x0)>(x3) && (x1)>(x3)) || ((y0)<(y2) && (y1)<(y2)) || ((y0)>(y3) &&
(y1)>(y3)) )) )
},
get_text: function(default_text) {
if (this.custom_text && !(default_text))
return this.custom_text;
if (!(this.default_text))
this.default_text = "Type your text here.";
// is the default text already TEXTFORMAT'ted?
if (this.default_text.toLowerCase().indexOf('You have not uploaded any photos. Click here to upload photos.';
} else if (photos.length==0) {
document.getElementById('thumbnails').innerHTML = 'This Photo Box is empty.
';
} else {
var thumbs = document.getElementById('thumbnails');
var images = new Array();
thumbs.innerHTML = '';
for (var i in photos) {
var tc = html_photo_thumb(photos[i].photo_id);
var img = tc.getElementsByTagName('img').item(0);
YAHOO.util.Dom.generateId(img);
photos[i].img_id = img.id;
//images.push(img);
//set_thumbnail_drag(img);
thumbs.appendChild(tc);
}
thumbs.innerHTML = thumbs.innerHTML;
for (var i in photos) {
var img = document.getElementById(photos[i].img_id);
img.photo = photos[i];
set_thumbnail_drag(img);
}
}
function set_thumbnail_drag(img) {
YAHOO.util.Dom.generateId(img)
img.dd = new YAHOO.pwd.DDThumb(img.id, 'photos-group', {centerFrame:true, size:0.8, opacity:0.8 }); // dropped into "page-window" group targets
//img.dd = new YAHOO.util.DDProxy(img.id, 'photos-group', { centerFrame: true } );
img.dd.onDragDrop = on_drag_drop;
}
function on_drag_drop(event, drop_target_id) {
var el = document.getElementById(drop_target_id);
// QQQQQQQQ
// dragged thumb to calendar day edit
if (drop_target_id=="grid-edit-day-area-photo") {
grid_day_editor.drop_photo(this.getEl().photo.photo_id);
return;
}
// dragged thumb to calendar grid
else if (drop_target_id.match(/^gridtarget/i)) {
grid_day_editor.edit_day(el);
grid_day_editor.drop_photo(this.getEl().photo.photo_id);
return;
}
// not a page window (probably another thumbnail)
if (!(el.prnt) || !(el.prnt.page_window_id))
return;
// PageWindowBase.drop_photo()...
el.prnt.drop_photo(this.getEl().photo.photo_id, this.getEl(), this.getEl().photo);
}
function photo_thumb_url(photo_id) {
return '/myphotos/thumbnails/0/' + photo_id + '.jpg';
}
function get_photobox_photos(photobox_id) {
var photos = [];
var show_photos = [];
for (i in photos) {
if (photos[i].photobox_id == photobox_id)
show_photos.push(photos[i]);
}
return show_photos;
}
function html_photo_thumb(photo_id) {
var table = document.createElement('table');
var tr = document.createElement('tr');
var td = document.createElement('td');
var img = document.createElement('img');
img.src = photo_thumb_url(photo_id);
table.setAttribute('cellspacing', 0);
table.setAttribute('cellpadding', 0);
td.appendChild(img); tr.appendChild(td); table.appendChild(tr)
YAHOO.util.Dom.addClass(table, 'thumb-container');
return table;
var img = document.createElement('img');
img.src = photo_thumb_url(photo_id);
var div = document.createElement('div');
div.appendChild(img);
return div;
return;
var table = document.createElement('table');
var tr = document.createElement('tr');
var td = document.createElement('td');
var img = document.createElement('img');
img.src = photo_thumb_url(photo_id);
table.setAttribute('cellspacing', 0);
table.setAttribute('cellpadding', 0);
td.appendChild(img); tr.appendChild(td); table.appendChild(tr)
//YAHOO.util.Dom.addClass(table, 'thumb-container');
return table;
var table = document.createElement('table');
var tr = document.createElement('tr');
var td = document.createElement('td');
var img = document.createElement('img');
img.src = photo_thumb_url(photo_id);
td.appendChild(img); tr.appendChild(td); table.appendChild(tr);
YAHOO.util.Dom.addClass(table, 'thumbnail')
table.setAttribute('cellpadding', 0);
table.setAttribute('cellspacing', 0);
return table;
}
}
/** UTILITY FUNCITONS **/
function yalert(title, msg, buttons) {
//YAHOO.log("ALERT: " + title + " /// " + msg);
return;
/* show message */
var dlg = new YAHOO.widget.SimpleDialog("dlg",
{
close: false,
width: "240px",
fixedcenter: true,
modal: true,
draggable: false
}
);
dlg.setHeader(title);
dlg.setBody(msg);
if (!(buttons))
dlg.cfg.queueProperty("buttons", [ { text: "OK", handler: function() { this.hide(); } } ]);
else
dlg.cfg.queueProperty("buttons", buttons);
dlg.cfg.queueProperty("zIndex", 52000);
dlg.render(document.body);
if (dlg.mask)
dlg.mask.style.zIndex = 51999;
}
function mixin(child, parent) {
//alert(typeof parent);
for (var i in parent) {
if (typeof parent[i]=='function')
child[i] = parent[i];
}
//return child;
}
function loading_el(message) {
var el = document.createElement('div');
el.innerHTML = message ? message : 'Please wait...';
YAHOO.util.Dom.addClass(el, 'loading');
return el;
}
function fix_png(element,sizingMethod) {
if (!(window.ActiveXObject && !(window.XMLHttpRequest)))
return;
if (!(sizingMethod))
sizingMethod='image';
var src = element.src;
element.src = '/images/transparent1px.gif';
// set filter
//element.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "',sizingMethod='scale')";
element.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + src + "',sizingMethod='" + sizingMethod + "')";
}
// clones simple objects
function clone_object(obj, deep) {
var clone = {};
for (i in obj) {
if (typeof(obj[i])=='object' && deep)
clone[i]=clone_object(obj[i], true);
else if (typeof obj[i]!='function')
clone[i]=obj[i];
}
return clone;
}
// adds/removes no-display class for object with id
function set_no_display(id, no_display_true) {
var el = typeof id!='object' ? document.getElementById(id) : id;
if (!(el))
return false;
if (no_display_true)
YAHOO.util.Dom.addClass(el, 'no-display');
else
YAHOO.util.Dom.removeClass(el, 'no-display');
}
function show(id) {
set_no_display(id, false);
}
function hide(id) {
set_no_display(id, true);
}
// repeat str n_times
function s_repeat(str, n_times) {
var tmp = new Array(n_times+1);
return tmp.join(str);
}
// dump object in readable format
function to_s(obj, depth, indent) {
var i = indent ? indent : 2;
var d = depth ? depth : 0;
var sep = ' ';
var s = s_repeat(sep, i*d) + "{\n";
for (var idx in obj) {
if (obj[idx] instanceof Object)
s += (s_repeat(sep, i*d+i) + idx + ":\n" + to_s(obj[idx], d+2));
else if (!(obj[idx] instanceof Function))
s += (s_repeat(sep, i*d+i) + idx + ": " + obj[idx] + "\n");
else if (false)
s += (s_repeat(sep, i*d+i) + idx + ": [" + typeof(obj[idx]) + "]\n");
}
s += s_repeat(sep, i*d) + "}\n";
return s;
}