ysc = new Object(); ysc.pluginURL = 'http://www.ihotlaunch.com/wp-content/plugins/yahoo-shortcuts/'; ysc.imageURL = 'http://www.ihotlaunch.com/wp-content/plugins/yahoo-shortcuts/images/'; ysc.agent_is_msie = false; ysc.agent_is_safari2 = false; ysc.img_ext = 'png'; ysc.saved_y_script = ''; ysc.page = 'publish'; // Copyright (c) 2007 Yahoo! Inc. All rights reserved. // The copyrights to the software code in this file are licensed under the (revised) BSD open source license. // the ysc object and some of its props are generated by our php file ysc.scan_timer = null; // scans post periodically for changes ysc.idle_timer = null; // scans post on idle, according to onchange and event hooks in mce ysc.cached_post_content = '
'; // currently, an 'empty', fresh post looks like this ysc.rte = null; // rich text editor instance ysc.inited = false; ysc.rte_feedback = false; ysc.n_shortcuts = 0; ysc.should_preprocess_text = false; ysc.scan_on_idle = false; ysc.scan_freq = 15000; ysc.empty = function(obj) { if (typeof(obj) == 'object') { for(var a in obj) { return false; } } else if(typeof(obj) == 'string') { return (obj.length === 0); } return true; }; ysc.attach_hover = function(obj_or_selector) { if (ysc.agent_is_safari2) { jQuery(obj_or_selector).hover( function() { ysc.safari2_force_redraw(); } , function() { ysc.safari2_force_redraw(); } ); } if (ysc.agent_is_msie) { jQuery(obj_or_selector).hover( function() { jQuery(this).addClass('hover'); } , function() { jQuery(this).removeClass('hover'); } ); } }; ysc.detach_hover = function(obj_or_selector) { jQuery(obj_or_selector).hover(function() {}, function() {}); }; ysc.editor_content_ready = function() { ysc.generate_annotationSet(ysc.saved_y_script); ysc.start_scan_timer(1000); ysc.update_icons_in_text(); }; ysc.init = function() { if (jQuery('#preview_rendering').size() > 0) { ysc.page = 'preview'; } else if (jQuery('#ysc_yahoo_this_post').size() > 0) { ysc.page = 'edit'; } // if publish, will be set on php side if (ysc.page == 'publish') { ysc.prepare_publish(); } else if (ysc.page == 'preview') { ysc.prepare_preview(); } else if (ysc.page == 'edit') { ysc.prepare_edit(); } ysc.inited = true; }; ysc.get_rte = function() { return ysc.rte; }; ysc.idle_timeout = function() { if (ysc.scan_on_idle && ysc.post_is_dirty() && !ysc.preview_post_clicked) { ysc.detect_entities('update_dbx'); } }; ysc.mce_plugin = { getInfo: function() { return { longname : 'Yahoo! Shortcuts TinyMCE Plugin', author : 'Crowd Favorite', authorurl : 'http://crowdfavorite.com', infourl : '', version : "1.0" }; } , initInstance: function(instance) { ysc.rte = instance; } , removeInstance: function(instance) { ysc.rte = null; } , onChange: function(inst) { if(ysc.idle_timer) { clearTimeout(ysc.idle_timer); } ysc.idle_timer = setTimeout(ysc.idle_timeout, 1000); } , handleEvent: function(event) { if(ysc.idle_timer) { clearTimeout(ysc.idle_timer); } ysc.idle_timer = setTimeout(ysc.idle_timeout, 1000); return true; } , execCommand: function(editor_id, element, command, user_interface, value) { var rte = ysc.get_rte(); var focus = rte.getFocusElement(); if ((command == 'JustifyLeft' || command == 'JustifyRight' || command == 'JustifyCenter') && (focus.nodeName == 'IMG' && focus.className.match('ysc_embed_proxy'))) { var img = jQuery(focus); if (ysc.agent_is_msie) { var center_tag = img.parent('center'); if (center_tag.size()) { img.insertAfter(center_tag); center_tag.remove(); } } img.removeClass(); if (command == 'JustifyRight') { img.addClass('ysc_embed_proxy_right'); } else if (command == 'JustifyLeft') { img.addClass('ysc_embed_proxy'); } else if (command == 'JustifyCenter') { img.addClass('ysc_embed_proxy_center'); if (ysc.agent_is_msie) { img.wrap('
'); } } rte.execCommand('mceRepaint'); return true; } return false; } , cleanup : function(type, content) { var id_re = /]+)["']*/i; // id in $1 var img_re = /]+class\s*=\s*["']*ysc_embed_proxy[^\/>]*?\/>/i; var msie_center_img_re = /
.+class\s*=\s*["']*ysc_embed_proxy.*<\/center>/i; var tag_re = /name\s*=\s*["']*([^ \t\r\n"'>]+)["']*/i; // id in $1 var ralign_proxy_re = /class\s*=\s*["']*\w*\s*ysc_embed_proxy_right["']*/i; var calign_proxy_re = /class\s*=\s*["']*\w*\s*ysc_embed_proxy_center["']*/i; var ralign_div_re = /class\s*=\s*["']*\w*\s*ysc_embed_right[ "'>]/i; var calign_div_re = /class\s*=\s*["']*\w*\s*ysc_embed_center[ "'>]/i; var startPos, replaceStart, replaceEnd; var chunkBefore, chunkAfter; var results = null; var tag = ''; var align_right = false; var align_center = false; var class_ext = ''; var icon_src = ''; switch (type) { case 'insert_to_editor': while (id_re.test(content)) { results = id_re.exec(content); replaceStart = startPos = results.index; tag = results[1]; if (ysc.inited) { icon_src = ysc.get_icon_for_entity(tag); } else { icon_src = ysc.get_icon_for_entity(''); } replaceEnd = content.toLowerCase().indexOf('', startPos) + 6; align_right = ralign_div_re.test(content.substring(0, replaceEnd)); align_center = calign_div_re.test(content.substring(0, replaceEnd)); chunkBefore = content.substring(0, replaceStart); if (align_right) { class_ext = '_right'; } else if (align_center) { class_ext = '_center'; } else { class_ext = ''; } var imgHTML = ''; if (ysc.agent_is_msie && align_center) { imgHTML = '
' + imgHTML + '
'; } chunkAfter = content.substring(replaceEnd); content = chunkBefore + imgHTML + chunkAfter; } break; case 'get_from_editor': while (img_re.test(content)) { results = null; if (ysc.agent_is_msie) { results = msie_center_img_re.exec(content); } if (!results) { results = img_re.exec(content); } replaceStart = startPos = results.index; if (ysc.agent_is_msie && align_center) { replaceEnd = content.substring(startPos).search(/<\/center>/i) + replaceStart + 9; } else { replaceEnd = content.indexOf('/>', startPos) + 2; } align_right = ralign_proxy_re.test(content.substring(0, replaceEnd)); align_center = calign_proxy_re.test(content.substring(0, replaceEnd)); var nameResults = tag_re.exec(content.substring(startPos)); tag = (nameResults ? nameResults[1] : 'orphaned'); chunkBefore = content.substring(0, replaceStart); chunkAfter = content.substring(replaceEnd); if (align_right) { class_ext = '_right'; } else if (align_center) { class_ext = '_center'; } else { class_ext = ''; } var embedHTML = '
'; content = chunkBefore + embedHTML + chunkAfter; } break; } return content; } }; if (typeof(tinyMCE) !== 'undefined') { tinyMCE.addPlugin("yahoo_shortcuts", ysc.mce_plugin); } ysc.update_icons_in_text = function() { var text = ysc.get_post_text(); text = text.replace(/]+>/gi, function(proxy_img_tag) { var entity_id = proxy_img_tag.match(/name=["']*([^ "'>]+)["']*/)[1]; return proxy_img_tag.replace(/src=["']*([^ "'>]+)["']*/i, function(attribute, url) { return 'src="' + ysc.get_icon_for_entity(entity_id) + '"'; }); }); ysc.set_post_text(text); }; ysc.get_icon_for_entity = function(entity_tag) { ysc.generate_annotationSet(ysc.saved_y_script); for (var id in YAHOO.Shortcuts.annotationSet) { var entity = YAHOO.Shortcuts.annotationSet[id]; if (ysc.entity_has_embed(entity)) { var embed_pair = entity.clientMetaData.embeds.split(':'); // embed_dom_id:moduleName if (embed_pair[0] == 'ysc_embed_' + entity_tag) { var embedObj = new YAHOO.Shortcuts.Embed(); return embedObj.getModuleIcon(embed_pair[1]); } } } return ysc.imageURL + 'proxy.gif'; }; ysc.get_post_text = function() { var rte = ysc.get_rte(); if (rte !== null) { return rte.getBody().innerHTML; } else if (jQuery('#content').size() > 0) { return jQuery('#content')[0].value; } return ''; }; ysc.set_post_text = function(text) { var rte = ysc.get_rte(); if (rte !== null) { rte.execCommand('mceSetContent', false, text); ysc.cached_post_content = text; } else { jQuery('#content').attr('value', text); } }; ysc.showSearching = function() { var txt = ''; if (ysc.preview_post_clicked) { txt = 'Loading Preview ...'; jQuery('#ysc_yahoo_this_post').css('background', 'url(' + ysc.imageURL + '/btn_reviewpost_disabled.gif) no-repeat 16px 0px;'); } else if (ysc.n_shortcuts > 0) { txt = 'Searching for more...'; } else { txt = 'Searching...'; } jQuery('#ysc_searching_indicator').html(txt); }; ysc.hide_searching = function() { jQuery('#ysc_searching_indicator').html(' '); }; ysc.start_scan_timer = function(delay) { if (ysc.scan_timer) { clearTimeout(ysc.scan_timer); } if (typeof(delay) == 'undefined') { delay = ysc.scan_freq; } ysc.scan_timer = setTimeout( function() { if (ysc.post_is_dirty(true) && !ysc.preview_post_clicked) { ysc.detect_entities("update_dbx"); } else { ysc.start_scan_timer(); } }, delay); }; ysc.kill_scan_timer = function() { if (ysc.scan_timer) { clearTimeout(ysc.scan_timer); ysc.scan_timer = 0; } }; ysc.first_scan = true; ysc.post_is_dirty = function(update_cache) { var content = ysc.get_post_text(); var changed = (content != ysc.cached_post_content); if (ysc.first_scan) { ysc.first_scan = false; changed = true; } if (typeof(update_cache) !== 'undefined') { ysc.cached_post_content = content; } return changed; }; ysc.update_post_shortcut_num = function(num_shortcuts) { var str = ''; if (num_shortcuts == 1) { str = '' + num_shortcuts + ' Shortcut found.'; } else { str = '' + num_shortcuts + ' Shortcuts found.'; } jQuery('#ysc_num_shortcuts').html(str); }; // mode: ['update_dbx' | 'render_preview'] ysc.detect_entities = function(mode) { ysc.cached_post_content = ysc.get_post_text(); var data = {}; data.frcode = 'csc_wordpress'; data.text = ysc.preprocess_post_text(ysc.cached_post_content); data.input_format = 'html'; data.output = 'inline'; data.client_metadata = YAHOO.Shortcuts.getEntityManager().getClientMetaData(); ysc.showSearching(); ysc.kill_scan_timer(); jQuery.ajax({ type: 'POST', url: 'index.php?ysc_action=entity_funnel', dataType: 'html', data: data, success: function(response) { try { ysc.handle_response(response, mode); ysc.n_failures = 0; } catch (error) { if (error.name == 'ysc_connection_failure') { ysc.handle_connection_failure(error.mode); } } }, error: ysc.ajax_failure }); }; ysc.generate_annotationSet = function(script) { YAHOO.Shortcuts.annotationSet = {}; eval(script); if (typeof(YAHOO.Shortcuts.globals) != 'undefined') { // looks weird, but evalling the script only populates the object; // this method takes care of dependencies. YAHOO.Shortcuts.globals.setAnnotationSet(YAHOO.Shortcuts.annotationSet); } }; ysc.handle_response = function(response, mode) { if (response.indexOf('__ysc_annotation_request_failed__') >= 0) { throw { name: 'ysc_connection_failure', mode: mode }; } var script_tag_open = response.toLowerCase().indexOf('= 0) { var start = script_tag_open + response.indexOf('>', script_tag_open) + 1; response_script = response.substring(start , response.toLowerCase().indexOf('') - 1); if (response_script.indexOf('YAHOO.Shortcuts.annotationSet') == -1) { // mild sanity-checking throw { name: 'ysc_connection_failure', mode: mode }; } } var response_markup = response; if (response_script !== '') { // 9 + the newline after the script tag = 10 // we must de-slash it, also. response_markup = response.substring(response.indexOf('') + 10).replace(/\\/g, ''); } ysc.n_shortcuts = 0; ysc.generate_annotationSet(response_script); for (var entity in YAHOO.Shortcuts.annotationSet) { ysc.n_shortcuts++; } ysc.hide_searching(); ysc.update_post_shortcut_num(ysc.n_shortcuts); if (mode == 'update_dbx') { ysc.generate_annotationSet(ysc.saved_y_script); ysc.start_scan_timer(); } else if (mode == 'render_preview') { ysc.set_post_text(response_markup); var post_form = jQuery('#post'); post_form.append(''); post_form.append(''); post_form[0].ysc_entity_script.value = YAHOO.Shortcuts.getEntityManager().getJSONString(); // our form's dom element submit function is hidden by the save button, // which someone decided to call 'submit'. var s = jQuery('#post')[0].submit; if (typeof(s) == 'function') { // invoking s directly does not seem to work. jQuery('#post')[0].submit(); } else if (typeof(s) == 'object') { // doing it synchronously seems to cause problems. setTimeout( function() { jQuery('#post input[@name=submit]').click(); }, 1); } } }; ysc.n_failures = 0; ysc.handle_connection_failure = function(mode) { ysc.hide_searching(); jQuery('#ysc_searching_indicator').html('Could not contact Yahoo.'); if (ysc.n_failures > 5) { // saving for posterity: we may want to take some action on this in the future. ysc.n_failures = 0; } else { ysc.n_failures++; } if (mode == 'render_preview') { alert('The Yahoo Shortcuts plugin is having difficulty contacting Yahoo.'); if (mode == 'render_preview') { ysc.preview_post_clicked = false; jQuery('#ysc_yahoo_this_post').css('background', 'url(' + ysc.imageURL + '/btn_reviewpost.gif) no-repeat 16px 0px;'); } } }; ysc.ajax_failure = function(request_obj, error_string, exception) { ysc.hide_searching(); ysc.start_scan_timer(); }; ysc.preview_post_clicked = false; ysc.preview_post = function() { if (ysc.preview_post_clicked) { return; } else { ysc.preview_post_clicked = true; ysc.detect_entities('render_preview'); } }; ysc.entity_has_client_metadata = function(entity_tag) { var found = false; for (var t in YAHOO.Shortcuts.annotationSet) { if (t == entity_tag) { found = true; if (typeof(YAHOO.Shortcuts.annotationSet[t].clientMetaData) != 'undefined' && !ysc.empty(YAHOO.Shortcuts.annotationSet[t].clientMetaData)) { return true; } } if (found) { break; } } return false; }; ysc.preprocess_post_text = function(text) { // do this regardless text = text.replace(/ _?\$events="null"/g, ''); if (ysc.should_preprocess_text) { text = ysc.strip_free_entity_tags(text); text = ysc.normalize_spans(text); } return text; }; ysc.normalize_spans = function(text) { text = ysc.quote_attributes(text); text = text.replace(//g, ''); text = text.replace(/(id="[^"]")\s+(class="yshortcuts")/g, '$2 $1'); // in case reversed return text; }; ysc.quote_attributes = function(text) { var class_re = /class=([^ >'"]+)/gi; var id_re = /id=([^ >'"]+)/gi; text = text.replace(class_re, 'class="$1"'); text = text.replace(id_re, 'id="$1"'); return text; }; // by "free" we mean "no client metadata" ysc.strip_free_entity_tags = function(string){ var span_re = /]+.*/i; var id_re = /id\s*=\s*["']*([^ \t\r\n"'>]+)["']*/i; if (typeof(string) !== 'string' || string === '' || !span_re.test(string)) { return string; } var next_tag = function(string, offset) { if (typeof(offset) != 'undefined') { string = string.substring(offset); } var span_result = span_re.exec(string); if (span_result && span_result.length) { var id_result = id_re.exec(span_result[0]); if (id_result && id_result.length) { return { startIndex: span_result.index, id: id_result[1] }; } } return null; }; var offset, start, end; start = end = offset = 0; var result = ''; var current_tag = null; while (current_tag = next_tag(string, offset)) { start = current_tag.startIndex + offset; result += string.substring(offset, start); // stuff before span open if (!ysc.entity_has_client_metadata(current_tag.id)) { start = string.indexOf('>', start) + 1; // skip to span close, keeping track of any interior spans end = ysc.find_close_tag('span', string.toLowerCase().substring(start)) + start; result += string.substring(start, end); // stuff between span open and span close offset = string.indexOf('>', end) + 1; // skip past span close tag } else { // add whole open tag end = string.indexOf('>', start) + 1; result += string.substring(start, end); offset = end; } } if (offset < string.length) { result += string.substring(offset); } return result; }; // passed string should start *after* the open tag. ysc.find_close_tag = function(tag_name, string) { var open_tag = '<' + tag_name; var close_tag = ''; var open = string.indexOf(open_tag); var close = string.indexOf(close_tag); if (open == -1 || open > close) { // no open tags in the string, at least not until after the first close tag. // return first close tag. return string.indexOf(close_tag); } else { var open_end = 0; while (open != -1 && close > open) { open_end = string.indexOf('>', open) + 1; close = ysc.find_close_tag(tag_name, string.substring(open_end)) + open_end; open = string.indexOf(open_tag, close + close_tag.length); close = string.indexOf(close_tag, open); } return string.indexOf(close_tag, close + close_tag.length); } return -1; }; ysc.prepare_edit = function() { jQuery('#ysc_yahoo_this_post')[0].onclick = ''; jQuery('#ysc_yahoo_this_post').bind('click', ysc.preview_post); if (jQuery('#grabit').size() > 0 && jQuery('#ysc_dbx').size() > 0) { jQuery('#ysc_dbx').prependTo(jQuery('#grabit')); } ysc.editor_content_ready(); }; // ------------------------ preview page functions // [entity_tag] => [object Shortcut] ysc.shortcuts = {}; ysc.awesomeness = 0; ysc.safari2_force_redraw = function() { if (ysc.awesomeness++ % 2) { jQuery('body').css('background', 'url(' + ysc.imageURL + '/blank.gif) repeat'); } else { jQuery('body').css('background', 'url(' + ysc.imageURL + '/blank2.gif) repeat'); } }; ysc.Menu = function(shortcut) { this.shortcut = shortcut; this.mode = shortcut.mode; this.entity_tag = shortcut.entity_tag; this.is_open = false; this.is_opening = false; this.is_closing = false; this.visible = true; this.enabled = true; }; ysc.Menu.prototype.should_animate = function() { // 1. safari 2 canvas redraw reluctance breaks menu animations. // 2. jquery 1.1.4 NaN animation bug bug only manifests on ie, when easing left or right. go figure. // 3. center aligned: deferring. return ( !ysc.agent_is_safari2 && (this.mode == 'link' || !ysc.agent_is_msie) && (this.shortcut.get_embed_float_side() != 'center') ); }; ysc.Menu.prototype.open = function() { ysc.close_menus(); var m = this; if (this.should_animate()) { this.is_opening = true; this.render(); var menu = jQuery('#ysc_menu_' + this.entity_tag); if (this.mode == 'embed') { var spec = {width: 'show'}; if (ysc.agent_is_msie) { spec.right = 'show'; } else { var float_side = this.shortcut.get_embed_float_side(); spec[float_side] = 'show'; } menu.hide(); menu.animate(spec, 'fast', 'linear', function() { m.is_opening = false; m.is_open = true; m.request_render(); }); } else { menu.hide(); menu.animate({height:'show'}, 'fast', 'linear', function() { m.is_opening = false; m.is_open = true; //m.request_render(); }); } } else { this.render(); this.is_open = true; this.request_render(function() { if (ysc.agent_is_safari2) { ysc.safari2_force_redraw(); } }); } }; ysc.Menu.prototype.close = function() { var m = this; if (this.should_animate()) { this.is_closing = true; this.render(); if (this.mode == 'embed') { var spec = {width: 'hide'}; var float_side = this.shortcut.get_embed_float_side(); spec[float_side] = 'hide'; jQuery('#ysc_menu_' + this.entity_tag).animate(spec, 'fast', 'linear', function() { m.is_closing = false; m.is_open = false; m.request_render(); }); } else { jQuery('#ysc_menu_' + this.entity_tag).animate({height:'hide'}, 'fast', 'linear', function() { m.is_closing = false; m.is_open = false; m.request_render(); }); } } else { this.render(); this.is_open = false; this.request_render(function() { if (ysc.agent_is_safari2) { ysc.safari2_force_redraw(); } }); } }; ysc.Menu.prototype.set_mode = function(mode) { this.mode = mode; this.request_render(); }; ysc.Menu.prototype.disable = function() { this.enabled = false; ysc.update_remove_shortcuts_link(); this.request_render(); }; ysc.Menu.prototype.enable = function() { this.enabled = true; ysc.update_remove_shortcuts_link(); this.request_render(); }; // coalesce render requests ... do it once asap after we drop to idle ysc.menu_render_reqs = {}; ysc.Menu.prototype.request_render = function(callback) { if (typeof(ysc.menu_render_reqs[this.entity_tag]) == 'undefined') { ysc.menu_render_reqs[this.entity_tag] = { timer:null, callbacks: [] }; } var my_reqs = ysc.menu_render_reqs[this.entity_tag]; if (my_reqs.timer === null) { var m = this; my_reqs.timer = setInterval( function() { m.render(); for(var i in my_reqs.callbacks) { my_reqs.callbacks[i](); } clearInterval(my_reqs.timer); my_reqs.timer = null; my_reqs.callbacks = []; }, 100); } if (typeof(callback) == 'function') { my_reqs.callbacks.push(callback); } }; ysc.Menu.prototype.render = function() { if (this.mode == 'link') { this.render_link(); } else { this.render_embed(); } }; ysc.Menu.prototype.render_embed = function() { var link_span = jQuery('#' + this.entity_tag); jQuery('#ysc_menu_container_' + this.entity_tag).remove(); var nobr = jQuery('#ysc_nobr_' + this.entity_tag); if (nobr.size() > 0) { var clone = link_span.clone(); // for Safari 2's sake: link_span.attr('id', ''); clone.insertAfter(nobr); nobr.remove(); } jQuery('#ysc_menu_' + this.entity_tag).remove(); jQuery('#ysc_menu_tab_' + this.entity_tag).remove(); jQuery('#ysc_embed_container_' + this.entity_tag).prepend(this.get_html()); var container = jQuery('#ysc_menu_' + this.entity_tag); var m = this; if (this.is_closing || !this.is_open) { jQuery('#ysc_menu_tab_' + this.entity_tag).unbind('click').click(function() { ysc.shortcuts[m.entity_tag].menu.open(); return false; }); } // stop bubbling mouse clicks that originate in our menu jQuery('#ysc_menu_' + this.entity_tag).click(function() {return false;}); this.update_selected_badge(); ysc.attach_hover('.ysc_menu li span'); if (!ysc.agent_is_msie) { ysc.attach_hover('.ysc_badge_select span.select_prev'); ysc.attach_hover('.ysc_badge_select span.select_next'); } }; ysc.Menu.prototype.render_link = function() { var link_span = jQuery('#' + this.entity_tag); jQuery('#ysc_menu_container_' + this.entity_tag).remove(); var nobr = jQuery('#ysc_nobr_' + this.entity_tag); if (nobr.size() === 0) { link_span.wrap(''); } link_span.after(this.get_container_html()); jQuery('#ysc_menu_container_' + this.entity_tag).append(this.get_html()); if (this.is_open || this.is_opening) { jQuery('#ysc_menu_' + this.entity_tag).css({ top:'16px', left:'-22px' }); jQuery('#ysc_menu_container_' + this.entity_tag).css('z-index', 2); } var m = this; if (this.is_opening || (this.is_open && !this.is_closing)) { jQuery('#ysc_menu_tab_' + this.entity_tag).unbind('click').click(function() { ysc.shortcuts[m.entity_tag].menu.close(); return false; }); } else if (this.is_closing || !this.is_open) { jQuery('#ysc_menu_tab_' + this.entity_tag).unbind('click').click(function() { ysc.shortcuts[m.entity_tag].menu.open(); return false; }); } // stop bubbling mouse clicks that originate in our menu jQuery('#ysc_menu_' + this.entity_tag).click(function() {return false;}); ysc.attach_hover('.ysc_menu li span'); }; ysc.Menu.prototype.get_container_html = function() { return '
'; }; ysc.Menu.prototype.get_embed_offset = function() { var float_side = this.shortcut.get_embed_float_side(); if (float_side == 'right') { return (jQuery('#ysc_embed_' + this.entity_tag).width() + 9) + 'px'; } else { var center_offset = 0; if (float_side == 'center') { var embed = jQuery('#ysc_embed_' + this.entity_tag + ' div.lwEmbed'); if (embed.size()) { center_offset = (jQuery('#ysc_embed_container_' + this.entity_tag).width() / 2) - (embed[0].offsetWidth / 2); } } if (this.is_open || this.is_opening || this.is_closing) { return (center_offset - 112) + 'px'; //'-112px'; } else { return (center_offset - 15) + 'px'; //'-15px'; } } }; ysc.Menu.prototype.get_html = function() { if (this.mode == 'embed') { if (this.is_open || this.is_opening || this.is_closing) { var badge_select = ''; var xtraclass = ''; var base_class = (this.shortcut.get_embed_float_side() == 'right' ? 'ysc_embed_menu_open_right' : 'ysc_embed_menu_open'); if (this.shortcut.get_num_modules() > 1) { xtraclass = ' multi'; badge_select = '' + '' + '' + '' + ''; } return '
' + '
    ' + '
  • ' + 'Hide this menu
  • ' + '
  • Remove
  • ' + '
  • ' + 'Convert to Link
  • ' + '
' + badge_select + '
'; } else { var disabled_class = (this.enabled ? '' : ' disabled'); var style = 'style="left:' + this.get_embed_offset() + ';' + (this.visible ? '' : 'display:none;') + '"'; var base_class = (this.shortcut.get_embed_float_side() == 'right' ? 'ysc_embed_menu_tab_right' : 'ysc_embed_menu_tab'); return '
'; } } else { if (this.is_open || this.is_opening || this.is_closing) { var tab = ''; if (this.enabled) { if (this.shortcut.get_num_modules() > 0) { return tab + ''; } else { return tab + ''; } } else { return tab + ''; } } else { var xtra = (this.enabled ? '' : ' disabled'); return ''; } } }; ysc.Menu.prototype.update_selected_badge = function() { var get_button = function(menu, which) { var str = '#ysc_badge_select_' + menu.entity_tag + ' span.select_' + which; var b = jQuery('#ysc_badge_select_' + menu.entity_tag + ' span.select_' + which); if (ysc.agent_is_msie) { if (b.size()) { return b; } else { b = jQuery('#ysc_badge_select_' + menu.entity_tag + ' span.select_' + which + '_hover'); if (b.size()) { return b; } else { return jQuery('#ysc_badge_select_' + menu.entity_tag + ' span.select_' + which + '_disabled'); } } } else { return b; } }; var disable = function(button, which) { if (ysc.agent_is_msie) { button.unbind(); // undo the hover button.removeClass().addClass('select_' + which + '_disabled'); } else { button.addClass('disabled'); } }; var enable = function(button, which) { if (ysc.agent_is_msie) { button.removeClass('select_' + which + '_disabled').addClass('select_' + which); button.unbind(); button.hover( function() { button.removeClass('select_' + which).addClass('select_' + which + '_hover'); }, function() { button.removeClass('select_' + which + '_hover').addClass('select_' + which); } ); } else { button.removeClass('disabled'); } }; var nModules = this.shortcut.get_num_modules(); var selected = this.shortcut.get_selected_module_index() + 1; var prev = get_button(this, 'prev'); var next = get_button(this, 'next'); var s = this.shortcut; jQuery('#ysc_badge_select_' + this.entity_tag + ' span.selected_badge_num').html('Badge ' + selected + ' of ' + nModules); prev.unbind('click'); next.unbind('click'); if (selected == 1) { disable(prev, 'prev'); } else { enable(prev, 'prev'); prev.bind('click', function() { s.decrement_selected_badge(); }); } if (selected == nModules) { disable(next, 'next'); } else { enable(next, 'next'); next.bind('click', function() { s.increment_selected_badge(); }); } }; ysc.Shortcut = function(entity_tag, mods) { this.inited = false; this.entity_tag = entity_tag; this.modules = []; this.module_name = ''; this.selected_module_index = 0; this.preserve_embed_loc = false; var s = this; jQuery.each(mods, function(key, value) { if (key != 'numMods') { s.modules.push({ 'name': key, 'object': value }); } }); if (this.get_num_modules() > 0) { this.set_module_name(this.modules[0].name); } this.container_id = ''; this.mode = 'link'; this.menu = new ysc.Menu(this); // calculate it once. currently can't be changed on the preview page this.set_embed_float(this.calculate_embed_float()); this.inited = true; }; ysc.Shortcut.prototype.get_num_modules = function() { return this.modules.length; }; ysc.Shortcut.prototype.increment_selected_badge = function() { this.selected_module_index++; this.set_module_name(this.modules[this.selected_module_index].name); this.menu.update_selected_badge(); }; ysc.Shortcut.prototype.decrement_selected_badge = function() { this.selected_module_index--; this.set_module_name(this.modules[this.selected_module_index].name); this.menu.update_selected_badge(); }; ysc.Shortcut.prototype.set_module_name = function(name) { this.module_name = name; if (this.mode == 'embed') { YAHOO.Shortcuts.getEntityManager().attachEmbed(this.entity_tag, this.module_name, 'ysc_embed_' + this.entity_tag); } }; ysc.Shortcut.prototype.get_selected_module_index = function() { return this.selected_module_index; }; ysc.Shortcut.prototype.set_container_id = function(id) { this.container_name = id; }; // 'embed' | 'link' ysc.Shortcut.prototype.set_mode = function(mode) { if (mode == 'embed' && this.mode != 'embed') { if (this.modules.length > 0) { this.place_embed_container(); YAHOO.Shortcuts.getEntityManager().attachEmbed(this.entity_tag, this.module_name, 'ysc_embed_' + this.entity_tag); YAHOO.Shortcuts.getEntityManager().disableLink(this.entity_tag); jQuery('#' + this.entity_tag).removeAttr('style').addClass('highlighted'); this.mode = mode; this.menu.set_mode(mode); } } else if (mode == 'link' && this.mode != 'link') { jQuery('#' + this.entity_tag).removeClass('highlighted'); YAHOO.Shortcuts.getEntityManager().enableLink(this.entity_tag); YAHOO.Shortcuts.getEntityManager().detachEmbed(this.entity_tag, 'ysc_embed_' + this.entity_tag); this.remove_embed_container(this.is_embed_preserved()); this.mode = mode; this.menu.set_mode(mode); } }; ysc.Shortcut.prototype.disable = function() { if (this.mode == 'embed') { YAHOO.Shortcuts.getEntityManager().detachEmbed(this.entity_tag, 'ysc_embed_' + this.entity_tag); this.remove_embed_container(this.is_embed_preserved()); this.mode = 'link'; } YAHOO.Shortcuts.getEntityManager().disableLink(this.entity_tag); jQuery('#' + this.entity_tag).removeAttr('style'); jQuery('#' + this.entity_tag).removeClass('highlighted'); this.menu.set_mode(this.mode); this.menu.disable(); }; ysc.Shortcut.prototype.enable = function() { if (this.mode == 'embed') { this.place_embed_container(); YAHOO.Shortcuts.getEntityManager().attachEmbed(this.entity_tag, this.module_name, 'ysc_embed_' + this.entity_tag); } else { YAHOO.Shortcuts.getEntityManager().enableLink(this.entity_tag); } this.menu.enable(); }; ysc.Shortcut.prototype.is_enabled = function() { return this.menu.enabled; }; ysc.Shortcut.prototype.is_embed_preserved = function() { return this.preserve_embed_loc; }; ysc.Shortcut.prototype.remove_embed_container = function(set_placeholder) { var container = jQuery('#ysc_embed_container_' + this.entity_tag); if (container.size() > 0) { if (set_placeholder) { jQuery('#ysc_embed_container_' + this.entity_tag).after(this.get_embed_placeholder_html('hidden')); } jQuery('#ysc_embed_container_' + this.entity_tag).remove(); } }; ysc.Shortcut.prototype.get_embed_placeholder_html = function(hidden) { hidden = ((typeof(hidden) !== 'undefined') ? ' hidden' : ''); var className = 'ysc_embed'; var float_side = this.get_embed_float_side(); if (float_side == 'right'){ className = 'ysc_embed_right'; } else if (float_side == 'center') { className = 'ysc_embed_center'; } return ''; }; ysc.Shortcut.prototype.get_embed_container_html = function() { var float_side = this.get_embed_float_side(); var className = 'ysc_embed_container'; if (float_side == 'right') { className = 'ysc_embed_container_right'; } else if (float_side == 'center') { className = 'ysc_embed_container_center'; } return '
' + this.get_embed_placeholder_html() + '
'; }; ysc.Shortcut.prototype.place_embed_container = function() { var link_span = jQuery('#' + this.entity_tag); var placeholder = jQuery('#ysc_embed_' + this.entity_tag); if (placeholder.size() > 0) { // use the already-present placeholder if we've got one placeholder.attr('id', ''); placeholder.after(this.get_embed_container_html()); placeholder.remove(); } else { var embed_html = this.get_embed_container_html(); var p = link_span.parents('p'); if (p.size() > 0) { var child_containers1 = p.children('.ysc_embed_container'); var child_containers2 = p.children('.ysc_embed_container_right'); var child_placeholders = p.children('.ysc_embed'); if (child_containers1.size() === 0 && child_containers2.size() === 0 && child_placeholders.size() === 0) { // no embeds already present p.prepend(embed_html); } else { p.after('

' + embed_html + '

'); } } else { // put it at the top of the entry. p = link_span.parents('.entry'); if (p.size() > 0) { p.prepend(embed_html); } } } }; ysc.Shortcut.prototype.calculate_embed_float = function() { var entity = YAHOO.Shortcuts.annotationSet[this.entity_tag]; var has_embed = ysc.entity_has_embed(entity); if (has_embed) { var embed_pair = entity.clientMetaData.embeds.split(':'); // embed_dom_id:moduleName var embed = jQuery('#' + embed_pair[0]); if (embed.size()) { var className = embed.attr('class'); if (className.search(/_right/) > -1) { return 'right'; } else if (className.search(/_center/) > -1) { return 'center'; } } } return 'left'; }; ysc.Shortcut.prototype.get_embed_float_side = function() { return this.embed_float_side; }; ysc.Shortcut.prototype.set_embed_float = function(side) { this.embed_float_side = side; }; ysc.close_menus = function() { jQuery.each(ysc.shortcuts, function(entity_tag, shortcut) { var m = shortcut.menu; if (m.is_open && !m.is_opening && !m.is_closing) { m.close(); } }); }; ysc.prepare_preview = function() { ysc.n_shortcuts = 0; var n_modules = 0; if (typeof(ysc.saved_y_script) !== 'undefined' && ysc.saved_y_script !== '') { ysc.generate_annotationSet(ysc.saved_y_script); } jQuery.each(YAHOO.Shortcuts.annotationSet, function(entity_tag, entity) { var embedObj = new YAHOO.Shortcuts.Embed(); var modules = embedObj.getModules(entity); n_modules += modules.numMods; var has_embed = ysc.entity_has_embed(entity); var is_disabled = ysc.entity_is_disabled(entity); var embed_pair = []; if (has_embed) { embed_pair = entity.clientMetaData.embeds.split(':'); // embed_dom_id:moduleName ysc.synch_embeds(entity_tag, entity); // may have changed after synching ... has_embed = ysc.entity_has_embed(entity); } var shortcut = new ysc.Shortcut(entity_tag, modules); ysc.shortcuts[entity_tag] = shortcut; if (has_embed) { shortcut.preserve_embed_loc = true; shortcut.set_mode('embed'); shortcut.set_module_name(embed_pair[1]); } else if (is_disabled) { shortcut.disable(); } else { shortcut.set_mode('link'); shortcut.enable(); } ysc.n_shortcuts++; }); jQuery('#ysc_preview_num_shortcuts').html(ysc.n_shortcuts + ' Shortcut' + (ysc.n_shortcuts > 1 ? 's' : '')); if (n_modules > 0) { jQuery('#convert_shortcuts').toggle( function() { ysc.convert_all_shortcuts('embed'); } , function() { ysc.convert_all_shortcuts('link'); } ); } else { jQuery('#convert_shortcuts').addClass('disabled'); } jQuery('#remove_shortcuts span').click(function() { ysc.remove_all_shortcuts(); return false; }); if (ysc.agent_is_msie) { ysc.attach_hover('#preview_header li span'); ysc.attach_hover('#submit_buttons input'); } jQuery('#submenu a.current').attr('href', window.location); jQuery('body').bind('click', function() { ysc.close_menus(); }); }; ysc.entity_is_disabled = function(entity) { return (typeof(entity.clientMetaData) != 'undefined') && (typeof(entity.clientMetaData.disabled) != 'undefined') && (entity.clientMetaData.disabled == 'true'); }; ysc.entity_has_embed = function(entity) { return (typeof(entity.clientMetaData) !== 'undefined' && typeof(entity.clientMetaData.embeds) !== 'undefined') && !(ysc.empty(entity.clientMetaData.embeds)); }; ysc.synch_embeds = function(entity_tag, entity) { if (ysc.entity_has_embed(entity)) { var embed_pair = entity.clientMetaData.embeds.split(':'); // embed_dom_id:moduleName var embed = jQuery('#' + embed_pair[0]); if (embed.size()) { jQuery('#' + embed_pair[0]).attr('id', 'ysc_embed_' + entity_tag); YAHOO.Shortcuts.annotationSet[entity_tag].clientMetaData.embeds = 'ysc_embed_' + entity_tag + ':' + embed_pair[1]; } else { // assume user deleted proxy icon YAHOO.Shortcuts.annotationSet[entity_tag].clientMetaData.embeds = ''; } } }; ysc.enable_all_shortcuts = function() { ysc.link_update_lock = true; // wait till we're done jQuery.each(ysc.shortcuts, function(entity_tag, shortcut) { if (!shortcut.is_enabled()) { shortcut.enable(); } }); ysc.link_update_lock = false; ysc.update_remove_shortcuts_link(); }; ysc.remove_all_shortcuts = function() { ysc.link_update_lock = true; // wait till we're done jQuery.each(ysc.shortcuts, function(entity_tag, shortcut) { shortcut.disable(); }); ysc.link_update_lock = false; ysc.update_remove_shortcuts_link(); }; ysc.link_update_lock = false; ysc.update_remove_shortcuts_link = function() { if (ysc.link_update_lock) { return; } ysc.link_update_lock = true; var will_remove = true; var n_shortcuts = 0; var n_enabled = 0; for(var entity_tag in ysc.shortcuts) { n_enabled = (ysc.shortcuts[entity_tag].is_enabled()) ? n_enabled + 1 : n_enabled; n_shortcuts++; } // if majority are enabled, our link will be 'remove' if (n_enabled < Math.floor(n_shortcuts / 2)) { will_remove = false; } var link = jQuery('#remove_shortcuts span'); if(will_remove) { link.unbind('click'); link.html('Remove all Shortcuts'); // on a timeout instead of directly binding because msie activates the new binding // when bubbling back out of our click ... causing an infinite loop. setTimeout( function() { link.click(function() { ysc.remove_all_shortcuts(); return false; }); }, 1); } else { link.unbind('click'); link.html('Enable all Shortcuts'); setTimeout( function() { link.click(function() { ysc.enable_all_shortcuts(); return false; }); }, 1); } ysc.link_update_lock = false; }; ysc.convert_all_shortcuts = function(to_what) { jQuery.each(ysc.shortcuts, function(entity_tag, shortcut) { if (shortcut.is_enabled()) { shortcut.set_mode(to_what); } }); if (to_what == 'embed') { jQuery('#convert_shortcuts span').html('Convert all badges to links'); } else { jQuery('#convert_shortcuts span').html('Convert all links to badges'); } }; ysc.preview_submitted = function() { // strip our UI out, leaving only the embeds jQuery('div.ysc_menu_container').remove(); jQuery.each(ysc.shortcuts, function(entity_tag, shortcut){ if (shortcut.mode == 'embed' && shortcut.is_enabled()) { // we leave these in the post text var float_side = shortcut.get_embed_float_side(); if (float_side == 'right') { jQuery('#ysc_embed_container_' + entity_tag).after('
'); } else if (float_side == 'center') { jQuery('#ysc_embed_container_' + entity_tag).after('
'); } else { jQuery('#ysc_embed_container_' + entity_tag).after('
'); } } else { jQuery('#ysc_embed_' + entity_tag).remove(); } jQuery('#ysc_embed_container_' + entity_tag).remove(); var span = jQuery('#' + entity_tag); span.removeAttr('style'); span.removeClass('highlighted'); span.clone().insertAfter('#ysc_nobr_' + this.entity_tag); jQuery('#ysc_nobr_' + this.entity_tag).remove(); }); var post = jQuery('#preview_rendering').html(); if (ysc.agent_is_msie) { post = post.replace(/ _?\$events="null"/g, ''); post = post.replace(/<\/p>[\r\n]/gi, '<\/p>'); post = ysc.normalize_spans(post); } post = post.replace('&', '&'); jQuery('input[@name=ysc_content]').val(post); jQuery('input[@name=ysc_entity_script]').val(YAHOO.Shortcuts.getEntityManager().getJSONString()); }; // ------------------------ published functions ysc.prepare_publish = function() { var span, embed; jQuery.each(YAHOO.Shortcuts.annotationSet, function(entity_tag, entity) { ysc.synch_embeds(entity_tag, entity); span = jQuery('#' + entity_tag); embed = jQuery('#ysc_embed_' + entity_tag); if (span.size() > 0 && embed.size() > 0) { var s = span; // otherwise closure captures big scope, span continues to change embed.hover( function() { s.addClass('highlighted'); }, function() { s.removeClass('highlighted'); } ); } }); }; // ------------------------ start it up YAHOO.Shortcuts.YUI.util.Event.addListener(window, "load", function(e,obj) { // poll until we're ready if (typeof(YAHOO.Shortcuts.globals) == 'undefined') { setTimeout(function() { if (typeof(YAHOO.Shortcuts.globals) == 'undefined') { setTimeout(this, 250); } else { if (!ysc.inited) { ysc.init(); } } }, 250); } else { if (!ysc.inited) { ysc.init(); } } }, YAHOO.Shortcuts);