/** 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('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; }