/* * Kachingle medallion overlay controls. * (C) Copyright 2010, 2011 Kachingle Inc. * All Rights Reserved * Proprietary * */ // Controls for navigating within the overlay var main_menu_length = register_main_menu(); // special registration for main-menu register_module("register", go_to_module); register_module("top-kachinglers", go_to_user_profile); register_module("topsites", go_to_site_profile); register_module("wmlmh", go_to_user_profile); register_module("site-profile"); register_module("user-profile"); /////////// Need to do this for each module, once at the beginning! var default_module_id = "top-kachinglers", parent_module_id = "", current_module = null; /* if (return_module_id // This was an internally-triggered reload; (at initialization, == "") && color_state == "orange") // so user just logged out of medallion. // so hide the double-wide orange cta and reveal what's behind. document.getElementById('container-wide').style.display = 'none'; */ if (return_module_id) // This was an internally-triggered reload (on 1st load, this == ""), so the overlay is already open load_remaining_images(); // load it all now else { if (color_state != "orange") load_initial_images(); document.onmouseover = load_remaining_images; document.onmousedown = load_remaining_images; } // Decide which module to start with. On reloads, show whatever was showing before; on first load, or // if internally-triggered reload made module disappear (like wmlmh after log-out), use the default. if (!return_module_id || !document.getElementById(return_module_id)) return_module_id = default_module_id; show_module(return_module_id); function register_module(module_id, callback) { var module = document.getElementById(module_id); if (module) set_links_callback(module_id + "-menu", callback); } // Special case, needs to be done a little differently than the modules function register_main_menu() { // Remember the number of items in the menu because scroll() needs to know it. return set_links_callback("main-menu", go_to_module); } // Returns length of the menu but only needed / used by main menu function set_links_callback(menu_id, callback) { var menu_length = 0; var menu = document.getElementById(menu_id); if (!menu) return; var items = menu.childNodes; for (var i = 0; i < items.length; ++i) { var item = items[i]; if (item.nodeType == 1 // element nodes only (no comments or whitespace/text) && item.nodeName == "DIV") { // divs only if (item.getAttribute("data-target-id")) // returns "" or null if not present item.onclick = callback; // enable the click response menu_length++; // count number of menu items; this is for main menu specifically } } return menu_length; } function show_module(module_id) { if (!module_id || !document.getElementById(module_id)) // if explicit call from onclick passes garbage module_id = default_module_id; if (current_module) current_module.style.display = "none"; current_module = document.getElementById(module_id); current_module.style.display = "block"; return false; // suppress link-following when called from an } function go_to_module() { // "this" = the menu item element that was clicked var new_module_id = this.getAttribute("data-target-id"); // id for module to go to // if (new_module_id) // "" or null was returned if no data-target-id attribute present [but this is now prevented in set_links_callback] show_module(new_module_id); } function go_to_site_profile() { // get data from the menu item itself, to know what to display in the profile var img_src = this.getAttribute("data-img-src"), name = this.getAttribute("data-name"), kcount = this.getAttribute("data-kachingler-count"), site_url = this.getAttribute("data-site-url"), kdotcom_url = this.getAttribute("data-kdotcom-url"); // Store the parent globally, because we will need it if the user reloads the overlay. parent_module_id = "topsites"; // insert that data into the profile display var img = document.getElementById("site-profile-avatar"); img.src = img_src; img.alt = name; document.getElementById("site-profile-name").innerHTML = name; document.getElementById("site-profile-kachingler-count").innerHTML = kcount; document.getElementById("site-profile-link-to-site").onclick = function() { window.open(site_url); }; // this element is a submit button document.getElementById("site-profile-link-to-kdotcom").onclick = function() { window.open(kdotcom_url); }; // submit button // and show it show_module("site-profile"); } function go_to_user_profile() { var parent_module_link_back = this.getAttribute("data-parent-module-link-back"), img_src = this.getAttribute("data-img-src"), name = this.getAttribute("data-name"), num_sites_visited = this.getAttribute("data-num-sites-visited"), kdotcom_url = this.getAttribute("data-kdotcom-url"); parent_module_id = this.getAttribute("data-parent-module-id"); // Top Kachinglers or WMLMH var breadcrumb = document.getElementById("user-profile-breadcrumb"); breadcrumb.onclick = function() { return show_module(parent_module_id); }; breadcrumb.href = "/" + parent_module_link_back; breadcrumb.title = breadcrumb.innerHTML = parent_module_link_back; var img = document.getElementById("user-profile-avatar"); img.src = img_src; img.alt = name; document.getElementById("user-profile-name").innerHTML = name; var num_sites_element = document.getElementById("user-profile-num-sites-visited"), num_sites_text_attribute = num_sites_visited == 1 ? "data-singular" : "data-plural", num_sites_text = num_sites_element.getAttribute(num_sites_text_attribute); num_sites_element.innerHTML = num_sites_visited + num_sites_text; document.getElementById("user-profile-link-to-kdotcom").onclick = function() { window.open(kdotcom_url); }; show_module("user-profile"); } // automate the scroll controls, based on certain assumptions about how things are structured here. // total_items is the number of items returned by the mysql query // max_visible_items is fixed by the layout function scroll(menu_id, total_items, direction, scroll_button) { var menu = document.getElementById(menu_id); var wrapper_class = menu.offsetParent.className; // "big-wrapper" or "wrapper" or "main-menu-wrapper" var item_size = wrapper_class == "big-wrapper" ? 56 : 27; // heights in px of big and small menu items, respectively var max_visible_items = menu.offsetParent.offsetHeight / item_size; if (total_items <= max_visible_items) // all items fit, so no scrolling return; var menutop = menu.offsetTop; var hidden_items = total_items - max_visible_items; if (direction == "up") { if (menutop < 0) { var new_top = menutop + item_size; menu.style.top = new_top + "px"; nextElSib(scroll_button).className = "down"; // remove any "deactivated" from the down-arrow if (new_top >= 0) scroll_button.className = "up deactivated"; // add "deactivated" to up-arrow when limit reached } } else { var top_limit = - hidden_items * item_size; if (menutop > top_limit) { var new_top = menutop - item_size; menu.style.top = new_top + "px"; previousElSib(scroll_button).className = "up"; // remove any "deactivated" from the up-arrow if (new_top <= top_limit) scroll_button.className = "down deactivated"; // add "deactivated" to down-arrow when limit reached } } } // Image loading: asynchronous function load_initial_images() { // Load 5 images max load_images(default_module_id + "-menu", 5); } function load_remaining_images() { document.onmouseover = null; // execute this function only once document.onmousedown = null; load_images("top-kachinglers-menu"); load_images("topsites-menu"); if (color_state == "green" || color_state == "purple") load_images("wmlmh-menu"); } // Load num_items images into one menu. If num_items not present, get them all. function load_images(menu_id, num_items) { var menu = document.getElementById(menu_id); if (menu) { var items = menu.childNodes; if (!num_items) num_items = items.length; for (var i = 0, img_count = 0; i < items.length && img_count < num_items; ++i) { var item = items[i]; if (item.nodeType == 1 // element nodes only (no comments or whitespace/text) && item.className == "module-container-big") { // contains an image var img = firstElChild(firstElChild(item)), src = img.getAttribute("data-src"); // returns "" or null if not present if (src) { img.removeAttribute("data-src"); // so that this image won't be loaded again img.src = src; // load the image! ++img_count; } } } } } // Reload medallion in JS instead of plain link so that we can include the dynamic value of // the id attribute of the current module (and thereby return to the same module after reload). // return_to and site_id came from php variables captured in the skin; // action = "kachingle"/"kachingle_anonymous"/"stop_kachingle"/"logout". function medallion_action(return_to, site_id, action) { // Do this right away for instant feedback document.getElementById("cta").className = (action == "logout") ? "orange" // note the "orange" state overlay is actually purple! : (action == "stop_kachingle") ? "purple" : "green"; var return_module_id = current_module.id; // Site and user profiles are too complicated to return to. Return to their parent if (return_module_id == "site-profile" || return_module_id == "user-profile") return_module_id = parent_module_id; window.location.href = "/medallion.php?style=overlay" + "&return_to=" + return_to + "&site=" + site_id + "&action=" + action + "&return_module_id=" + return_module_id; } // Helper functions because IE8 and below don't have nextElementSibling and previousElementSibling, firstElementChild. Grrr.... // Note these are not really universal because they don't handle the nextElementSibling of the last child, // nor the previousElementSibling of the first child; nor the firstElementChild of an empty node. // But we never use them in a way that requires that to work. function nextElSib(node) { if (node.nextElementSibling) return node.nextElementSibling; var nextSib = node.nextSibling; while (nextSib.nodeType != 1) nextSib = nextSib.nextSibling; return nextSib; } function previousElSib(node) { if (node.previousElementSibling) return node.previousElementSibling; var prevSib = node.previousSibling; while (prevSib.nodeType != 1) prevSib = prevSib.previousSibling; return prevSib; } function firstElChild(node) { if (node.firstElementChild) return node.firstElementChild; var firstKid = node.firstChild; while (firstKid.nodeType != 1) firstKid = firstKid.nextSibling; return firstKid; }