/********************************************************** Manipulation and interaction with the overall Cloud ***********************************************************/ Cloud = { topic_count: 0, cancel_body_click: false, init: function(e) { logDebug('function: init'); topic_count = Server.next_topic_id; Event.observe('cloud_body', 'dblclick', Cloud.body_click, true); Event.observe('cloud_title', 'dblclick', Cloud.title_doubleclick, true); Helpers.setRoundedCorners("div.topic"); }, body_click: function(e) { logDebug('function: body_click'); if( Cloud.cancel_body_click ) { Cloud.cancel_body_click = false; } else { Topic.topic_create_client(Event.pointerX(e) + 'px', Event.pointerY(e) + 'px'); } // Remove explanation if present var explanation = $('gettingStarted'); if( explanation ) Element.remove(explanation); }, title_doubleclick: function(e) { var div = Event.element(e).parentNode; var divTxt = document.getElementsByClassName('text', div)[0]; var input = Helpers.insertInput(div, divTxt, divTxt.innerHTML, Cloud.title_blur); Element.removeClassName(div, 'dimmed'); }, title_blur: function(e) { var div = Event.element(e).parentNode; var divTxt = Helpers.removeInput(div); Event.observe('cloud_title', 'dblclick', Cloud.title_doubleclick, true); Sync.cloud_update_server(divTxt.innerHTML); } } /********************************************************** Manipulation and interaction with the cloud Topics ***********************************************************/ Topic = { topic_blur: function(e) { logDebug('function: topic_blur'); var input = Event.element(e); var content = $F(input).strip(); var div = input.parentNode; // Transfer text to div Topic.topic_removeInput(div); if( content != '' ) { if( div.id.search('new_') > -1 ) { // Save new topic element to server Sync.topic_create_server(div); } else { // Save existing topic element to server Sync.topic_update_server(div); } } else { // Kill the empty topic Topic.topic_delete(div); } }, topic_create_client: function(x, y) { logDebug('function: topic_create_client'); // Clone the template div var template = $('topic_'); var div = template.cloneNode(true); // Set element attributes var id = 'new_topic_' + Cloud.topic_count; div.id = id; Helpers.setAttribute(div, 'update_url', Server.topic_update_url + Cloud.topic_count); // Position element div.style.left = x; div.style.top = y; // Insert element $('cloud_body').appendChild(div); // Add rounded corners //Helpers.setRoundedCorners("div#" + id); // Attach events and count up client side counter Topic.topic_attach(div); Cloud.topic_count++; // Insert edit field Topic.topic_insertInput(div); }, topic_attach: function(div) { // Make topic draggable new Draggable(div); Draggables.addObserver( { element: div, onEnd: function(eventName, draggable, e){ if( draggable.element == div ) Sync.topic_update_server(div) } } ) // Attach events Event.observe(div.getElementsByTagName('textarea')[0], 'blur', function(){Sync.topic_update_server(div)}, false); Event.observe(document.getElementsByClassName('destroy', div)[0], 'click', function(){Topic.topic_destroy(div)}, false); Topic.topic_attach_text(div); }, topic_attach_text: function(div) { // TODO: Fix IE problem: document.getElementsByClassName('text', div) returns zero-length array in IE Event.observe(document.getElementsByClassName('text', div)[0], 'dblclick', Topic.topic_doubleclick, true); }, topic_set_id: function(transport, json) { var id = 'new_topic_' + json.client_id var elm = $(id); elm.id = 'topic_' + json.server_id; Helpers.setAttribute(elm, 'update_url', Server.topic_update_url + json.server_id); logDebug('function: topic_set_id: ' + elm.id + ', update_url: ' + Helpers.readAttribute(elm, 'update_url')); }, topic_delete: function(div) { Element.remove(div); }, topic_destroy: function(div) { // Remove client-side Element.remove(div); // Destroy server-side if not new if( div.id.search(/new_topic/) == -1 ) Sync.topic_destroy_server(div); }, topic_doubleclick: function(e) { var div = Event.element(e).parentNode; Topic.topic_insertInput(div); Event.stop(e); }, topic_insertInput: function(div) { var input = Helpers.insertInput(div, document.getElementsByClassName('text', div)[0], Helpers.getText(div), Topic.topic_blur); Element.addClassName(div, 'active'); }, topic_removeInput: function(div) { var divTxt = Helpers.removeInput(div); Element.removeClassName(div, 'active'); Topic.topic_attach_text(div); } } /********************************************************** Communication and synchronization with the server ***********************************************************/ Sync = { topic_create_server: function(div) { var new_id = div.id.split('_')[2]; logDebug('function: created topic with new_id = ' + new_id); new Ajax.Request( Server.topic_create_url, { parameters: 'topic[cloud_id]=' + Server.cloud_id + '&topic[text]=' + encodeURIComponent(Helpers.getText(div)) + '&topic[posx]=' + div.style.left + '&topic[posy]=' + div.style.top + '&client_id=' + new_id ,onComplete: Topic.topic_set_id } ); }, topic_update_server: function(div) { id = div.id.split('_')[1]; logDebug('function: topic_update_server'); new Ajax.Request(Helpers.readAttribute(div, 'update_url'), { parameters: '_method=put&id=' + id + '&topic[text]=' + encodeURIComponent(Helpers.getText(div)) + '&topic[notes]=' + encodeURIComponent(Helpers.getNotes(div)) + '&topic[posx]=' + div.style.left + '&topic[posy]=' + div.style.top } ) }, topic_destroy_server: function(div) { id = div.id.split('_')[1]; logDebug('function: topic_destroy_server'); new Ajax.Request(Helpers.readAttribute(div, 'update_url'), { parameters: '_method=delete' } ) }, cloud_update_server: function(title) { id = Server.cloud_id; logDebug('function: cloud_update_server'); new Ajax.Request(Server.cloud_update_url, { parameters: '_method=put&id=' + id + '&cloud[title]=' + encodeURIComponent(title) } ) } } /********************************************************** Various more or less "generic" helper methods ***********************************************************/ Helpers = { readAttribute: function(el, property) { elm = $(el); return (elm.getAttribute ? elm.getAttribute(property) || elm[property] : elm[property]); }, setAttribute: function(el, property, value) { elm = $(el); return (elm.setAttribute ? elm.setAttribute(property, value) : elm[property] = value); }, insertInput: function(outerDiv, txtDiv, textValue, blurMethod) { var input = document.createElement('INPUT'); Helpers.setAttribute(input, 'value', textValue); Event.observe(input, 'blur', blurMethod, false); Event.observe(input, 'keyup', function(e) { if( e.keyCode == Event.KEY_RETURN ) blurMethod(e) }, false); outerDiv.replaceChild(input, txtDiv); Field.focus(input); Field.select(input); return input; }, removeInput: function(div) { var input = div.getElementsByTagName("INPUT")[0]; var text = document.createTextNode(input.value); var divTxt = document.createElement('DIV'); Helpers.setAttribute(divTxt, 'class', 'text'); divTxt.appendChild(text); div.replaceChild(divTxt, input); return divTxt; }, getText: function(div) { return document.getElementsByClassName('text', div)[0].innerHTML; }, getNotes: function(div) { //logDebug(div.innerHTML); var textarea = div.getElementsByTagName('textarea')[0]; return $F(textarea); }, setRoundedCorners: function(selector) { if(NiftyCheck()) Rounded(selector, "all","#fff", "#FFF2BF", "smooth"); }, /*********************************************** * Bookmark site script- © Dynamic Drive DHTML code library (www.dynamicdrive.com) * This notice MUST stay intact for legal use * Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code ***********************************************/ bookmarksite: function(title,url) { if (window.sidebar) // firefox window.sidebar.addPanel(title, url, ""); else if(window.opera && window.print){ // opera var elem = document.createElement('a'); elem.setAttribute('href',url); elem.setAttribute('title',title); elem.setAttribute('rel','sidebar'); elem.click(); } else if(document.all)// ie window.external.AddFavorite(url, title); } }