Ajaxify Wordpress site with Social Plugins - javascript

I installed the plugin "Ajaxify Wordpress Site" and I'm also using "Easy Social Share buttons". The ajax loads the older/newer page content great, without loading the rest of the page (see it on www.squanderedink.com). However, when it's loaded, the social button counters do not update.
Easy Social Share gave me the following code, which must be placed after the ajax is done loading:
jQuery('.essb_links.essb_counters').essb_get_counters();
jQuery('.essb_counters .essb_links_list').essb_update_counters();
I've added the following code, but now the counters "stack" (i.e. they counters are duplicated overtime the page is refreshed via the ajax)
//Update social
$(document).ready(function () {
$("body").live("runScripts", function () {
jQuery('.essb_links.essb_counters').essb_get_counters();
jQuery('.essb_counters .essb_links_list').essb_update_counters();
});
$("body").trigger("runScripts"); // This line should also be added to the Ajax File
});
Thanks,
Kyle
AJAX code:
(function (window, undefined) {
// Prepare our Variables
var
History = window.History,
$ = window.jQuery,
document = window.document;
// Check to see if History.js is enabled for our Browser
if (!History.enabled) return false;
// Wait for Document
$(function () {
// Prepare Variables
var
// Application Specific Variables
rootUrl = aws_data['rootUrl'],
contentSelector = '#' + aws_data['container_id'],
$content = $(contentSelector),
contentNode = $content.get(0),
// Application Generic Variables
$body = $(document.body),
scrollOptions = {
duration: 800,
easing: 'swing'
};
// Ensure Content
if ($content.length === 0) $content = $body;
// Internal Helper
$.expr[':'].internal = function (obj, index, meta, stack) {
// Prepare
var
$this = $(obj),
url = $this.attr('href') || '',
isInternalLink;
// Check link
isInternalLink = url.substring(0, rootUrl.length) === rootUrl || url.indexOf(':') === -1;
// Ignore or Keep
return isInternalLink;
};
// HTML Helper
var documentHtml = function (html) {
// Prepare
var result = String(html).replace(/<\!DOCTYPE[^>]*>/i, '')
.replace(/<(html|head|body|title|script)([\s\>])/gi, '<div id="document-$1"$2')
.replace(/<\/(html|head|body|title|script)\>/gi, '</div>');
// Return
return result;
};
// Ajaxify Helper
$.fn.ajaxify = function () {
// Prepare
var $this = $(this);
// Ajaxify
$this.find('a:internal:not(.no-ajaxy,[href^="#"],[href*="wp-login"],[href*="wp-admin"])').on('click', function (event) {
// Prepare
var
$this = $(this),
url = $this.attr('href'),
title = $this.attr('title') || null;
// Continue as normal for cmd clicks etc
if (event.which == 2 || event.metaKey) return true;
// Ajaxify this link
History.pushState(null, title, url);
event.preventDefault();
return false;
});
// Chain
return $this;
};
// Ajaxify our Internal Links
$body.ajaxify();
// Hook into State Changes
$(window).bind('statechange', function () {
// Prepare Variables
var
State = History.getState(),
url = State.url,
relativeUrl = url.replace(rootUrl, '');
// Set Loading
$body.addClass('loading');
// Start Fade Out
// Animating to opacity to 0 still keeps the element's height intact
// Which prevents that annoying pop bang issue when loading in new content
if ('' != aws_data['transition']) {
$content.animate({
opacity: 0
}, 800);
}
if ('' != aws_data['loader']) {
$content
.html('<img src="' + rootUrl + 'wp-content/plugins/ajaxify-wordpress-site/images/' + aws_data['loader'] + '" />')
.css('text-align', 'center');
}
// Ajax Request the Traditional Page
$.ajax({
url: url,
success: function (data, textStatus, jqXHR) {
// Prepare
var
$data = $(documentHtml(data)),
$dataBody = $data.find('#document-body:first ' + contentSelector),
bodyClasses = $data.find('#document-body:first').attr('class'),
contentHtml, $scripts;
var $menu_list = $data.find('.' + aws_data['mcdc']);
//Add classes to body
jQuery('body').attr('class', bodyClasses);
// Fetch the scripts
$scripts = $dataBody.find('#document-script');
if ($scripts.length) $scripts.detach();
// Fetch the content
contentHtml = $dataBody.html() || $data.html();
if (!contentHtml) {
document.location.href = url;
return false;
}
// Update the content
$content.stop(true, true);
$content.html(contentHtml)
.ajaxify()
.css('text-align', '')
.animate({
opacity: 1,
visibility: "visible"
});
//Scroll to the top of ajax container
if ('' != aws_data['scrollTop']) {
jQuery('html, body').animate({
scrollTop: jQuery(contentSelector).offset().top
}, 1000);
}
//Append new menu HTML to provided classs
$('.' + aws_data['mcdc']).html($menu_list.html());
$body.ajaxify();
//Adding no-ajaxy class to a tags present under ids provided
$(aws_data['ids']).each(function () {
jQuery(this).addClass('no-ajaxy');
});
// Update the title
document.title = $data.find('#document-title:first').text();
try {
document.getElementsByTagName('title')[0].innerHTML = document.title.replace('<', '<')
.replace('>', '>')
.replace(' & ', ' & ');
} catch (Exception) {}
// Add the scripts
$scripts.each(function () {
var scriptText = $(this).html();
if ('' != scriptText) {
scriptNode = document.createElement('script');
scriptNode.appendChild(document.createTextNode(scriptText));
contentNode.appendChild(scriptNode);
} else {
$.getScript($(this).attr('src'));
}
});
// BuddyPress Support
if (aws_data['bp_status']) {
$.getScript(rootUrl + '/wp-content/plugins/buddypress/bp-templates/bp-legacy/js/buddypress.js');
}
$body.removeClass('loading');
// Inform Google Analytics of the change
if (typeof window.pageTracker !== 'undefined') window.pageTracker._trackPageview(relativeUrl);
// Inform ReInvigorate of a state change
if (typeof window.reinvigorate !== 'undefined' && typeof window.reinvigorate.ajax_track !== 'undefined')
reinvigorate.ajax_track(url); // ^ we use the full url here as that is what reinvigorate supports
},
error: function (jqXHR, textStatus, errorThrown) {
document.location.href = url;
return false;
}
}); // end ajax
}); // end onStateChange
}); // end onDomLoad
})(window); // end closure

Search for '// Update the content' and put it after that code.

Related

jQuery script works only once, then TypeError: $(...) is not a function

I've downloaded this script for use conditional fields in forms:
(function ($) {
$.fn.conditionize = function(options) {
var settings = $.extend({
hideJS: true
}, options );
$.fn.showOrHide = function(is_met, $section) {
if (is_met) {
$section.slideDown();
}
else {
$section.slideUp();
$section.find('select, input').each(function(){
if ( ($(this).attr('type')=='radio') || ($(this).attr('type')=='checkbox') ) {
$(this).prop('checked', false).trigger('change');
}
else{
$(this).val('').trigger('change');
}
});
}
}
return this.each( function() {
var $section = $(this);
var cond = $(this).data('condition');
// First get all (distinct) used field/inputs
var re = /(#?\w+)/ig;
var match = re.exec(cond);
var inputs = {}, e = "", name ="";
while(match !== null) {
name = match[1];
e = (name.substring(0,1)=='#' ? name : "[name=" + name + "]");
if ( $(e).length && ! (name in inputs) ) {
inputs[name] = e;
}
match = re.exec(cond);
}
// Replace fields names/ids by $().val()
for (name in inputs) {
e = inputs[name];
tmp_re = new RegExp("(" + name + ")\\b","g")
if ( ($(e).attr('type')=='radio') || ($(e).attr('type')=='checkbox') ) {
cond = cond.replace(tmp_re,"$('" + e + ":checked').val()");
}
else {
cond = cond.replace(tmp_re,"$('" + e + "').val()");
}
}
//Set up event listeners
for (name in inputs) {
$(inputs[name]).on('change', function() {
$.fn.showOrHide(eval(cond), $section);
});
}
//If setting was chosen, hide everything first...
if (settings.hideJS) {
$(this).hide();
}
//Show based on current value on page load
$.fn.showOrHide(eval(cond), $section);
});
}
}(jQuery));
I'm trying this because I need to use conditionize() in one of my tabs and when I reload the tab, all works but if I go to other tab and I return to the previous tab(where I need this works), I get that error.
When I change tabs, I'm only reloading one part of the page.
When I load the page this works perfectly, but if I try to call function again from browser console, it tells me that TypeError: $(...)conditionize() is not a function.
I have included the script in header tag and I'm calling it with this script on the bottom of body:
<script type="text/javascript">
$('.conditional').conditionize();
</script>
EDIT:
I have written
<script type="text/javascript">
console.log($('.conditional').conditionize);
setTimeout(function () {console.log($('.conditional').conditionize);}, 2);
</script>
and this print me at console the function, and when 2 milliseconds have passed, it print me undefined
I have found the solution.
Because any reason, the $ object and jQuery object are not the same in my code.
I have discovered it using this on browser console:
$===jQuery
This return false (This was produced because in other JS, I was using the noConflict(), which give me the problem)
Explanation: noConflict()
So I have solved it changing the last line of my JS by:
//Show based on current value on page load
$.fn.showOrHide(eval(cond), $section);
});
}
}($));
Putting the $ instead of 'jQuery'

ajaxify-html5.js reload only part of the page?

I found the following script online that makes your website load content with AJAX.
Everything works fine, but it also reload my music player that has to stay when clicking a link.
// Ajaxify
// v1.0.1 - 30 September, 2012
// https://github.com/browserstate/ajaxify
(function(window,undefined){
// Prepare our Variables
var
History = window.History,
$ = window.jQuery,
document = window.document;
// Check to see if History.js is enabled for our Browser
if ( !History.enabled ) {
return false;
}
// Wait for Document
$(function(){
// Prepare Variables
var
/* Application Specific Variables */
contentSelector = '#content,article:first,.article:first,.post:first',
$content = $(contentSelector).filter(':first'),
contentNode = $content.get(0),
$menu = $('#menu,#nav,nav:first,.nav:first').filter(':first'),
activeClass = 'active selected current youarehere',
activeSelector = '.active,.selected,.current,.youarehere',
menuChildrenSelector = '> li,> ul > li',
completedEventName = 'statechangecomplete',
/* Application Generic Variables */
$window = $(window),
$body = $(document.body),
rootUrl = History.getRootUrl(),
scrollOptions = {
duration: 800,
easing:'swing'
};
// Ensure Content
if ( $content.length === 0 ) {
$content = $body;
}
// Internal Helper
$.expr[':'].internal = function(obj, index, meta, stack){
// Prepare
var
$this = $(obj),
url = $this.attr('href')||'',
isInternalLink;
// Check link
isInternalLink = url.substring(0,rootUrl.length) === rootUrl || url.indexOf(':') === -1;
// Ignore or Keep
return isInternalLink;
};
// HTML Helper
var documentHtml = function(html){
// Prepare
var result = String(html)
.replace(/<\!DOCTYPE[^>]*>/i, '')
.replace(/<(html|head|body|title|meta|script)([\s\>])/gi,'<div class="document-$1"$2')
.replace(/<\/(html|head|body|title|meta|script)\>/gi,'</div>')
;
// Return
return $.trim(result);
};
// Ajaxify Helper
$.fn.ajaxify = function(){
// Prepare
var $this = $(this);
// Ajaxify
$this.find('a:internal:not(.no-ajaxy)').click(function(event){
// Prepare
var
$this = $(this),
url = $this.attr('href'),
title = $this.attr('title')||null;
// Continue as normal for cmd clicks etc
if ( event.which == 2 || event.metaKey ) { return true; }
// Ajaxify this link
History.pushState(null,title,url);
event.preventDefault();
return false;
});
// Chain
return $this;
};
// Ajaxify our Internal Links
$body.ajaxify();
// Hook into State Changes
$window.bind('statechange',function(){
// Prepare Variables
var
State = History.getState(),
url = State.url,
relativeUrl = url.replace(rootUrl,'');
// Set Loading
$body.addClass('loading');
// Start Fade Out
// Animating to opacity to 0 still keeps the element's height intact
// Which prevents that annoying pop bang issue when loading in new content
$content.animate({opacity:0},800);
// Ajax Request the Traditional Page
$.ajax({
url: url,
success: function(data, textStatus, jqXHR){
// Prepare
var
$data = $(documentHtml(data)),
$dataBody = $data.find('.document-body:first'),
$dataContent = $dataBody.find(contentSelector).filter(':first'),
$menuChildren, contentHtml, $scripts;
// Fetch the scripts
$scripts = $dataContent.find('.document-script');
if ( $scripts.length ) {
$scripts.detach();
}
// Fetch the content
contentHtml = $dataContent.html()||$data.html();
if ( !contentHtml ) {
document.location.href = url;
return false;
}
// Update the menu
$menuChildren = $menu.find(menuChildrenSelector);
$menuChildren.filter(activeSelector).removeClass(activeClass);
$menuChildren = $menuChildren.has('a[href^="'+relativeUrl+'"],a[href^="/'+relativeUrl+'"],a[href^="'+url+'"]');
if ( $menuChildren.length === 1 ) { $menuChildren.addClass(activeClass); }
// Update the content
$content.stop(true,true);
$content.html(contentHtml).ajaxify().css('opacity',100).show(); /* you could fade in here if you'd like */
// Update the title
document.title = $data.find('.document-title:first').text();
try {
document.getElementsByTagName('title')[0].innerHTML = document.title.replace('<','<').replace('>','>').replace(' & ',' & ');
}
catch ( Exception ) { }
// Add the scripts
$scripts.each(function(){
var $script = $(this), scriptText = $script.text(), scriptNode = document.createElement('script');
if ( $script.attr('src') ) {
if ( !$script[0].async ) { scriptNode.async = false; }
scriptNode.src = $script.attr('src');
}
scriptNode.appendChild(document.createTextNode(scriptText));
contentNode.appendChild(scriptNode);
});
// Complete the change
if ( $body.ScrollTo||false ) { $body.ScrollTo(scrollOptions); } /* http://balupton.com/projects/jquery-scrollto */
$body.removeClass('loading');
$window.trigger(completedEventName);
// Inform Google Analytics of the change
if ( typeof window._gaq !== 'undefined' ) {
window._gaq.push(['_trackPageview', relativeUrl]);
}
// Inform ReInvigorate of a state change
if ( typeof window.reinvigorate !== 'undefined' && typeof window.reinvigorate.ajax_track !== 'undefined' ) {
reinvigorate.ajax_track(url);
// ^ we use the full url here as that is what reinvigorate supports
}
},
error: function(jqXHR, textStatus, errorThrown){
document.location.href = url;
return false;
}
}); // end ajax
}); // end onStateChange
}); // end onDomLoad
})(window); // end closure
Let me explain it a little bit better.
The website has a music player that plays music while you are visiting the website, so clearly the music is not ment to stop whenever you click on a link.
This script works perfectly but it does refresh the whole page (using ajax) AND it is refreshing the music player.
There also is another script that comes with this one for changing the url and title ...
Thanks in advance, Greets
use the statechangecomplete event.
$(window).on('statechangecomplete', function(e, eventInfo){
//your code
})

Error 0x8007000e (NS_ERROR_OUT_OF_MEMORY)

I'm working on an addon to a forum and I get this error:
Error: Component returned failure code: 0x8007000e (NS_ERROR_OUT_OF_MEMORY) [nsIXPCComponents_Utils.evalInSandbox]
I read that the error means that the script goes into infinite loop until it fills the sandbox.
apparently the js file that leads to this error is script-compiler.js
this is the script:
var ddplus_gmCompiler={
// getUrlContents adapted from Greasemonkey Compiler
// http://www.letitblog.com/code/python/greasemonkey.py.txt
// used under GPL permission
//
// most everything else below based heavily off of Greasemonkey
// http://greasemonkey.mozdev.org/
// used under GPL permission
getUrlContents: function(aUrl){
var ioService=Components.classes["#mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var scriptableStream=Components
.classes["#mozilla.org/scriptableinputstream;1"]
.getService(Components.interfaces.nsIScriptableInputStream);
var channel=ioService.newChannel(aUrl, null, null);
var input=channel.open();
scriptableStream.init(input);
var str=scriptableStream.read(input.available());
scriptableStream.close();
input.close();
return str;
},
isGreasemonkeyable: function(url) {
var scheme=Components.classes["#mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService)
.extractScheme(url);
return (
(scheme == "http" || scheme == "https" || scheme == "file") &&
!/hiddenWindow\.html$/.test(url)
);
},
contentLoad: function(e) {
var unsafeWin=e.target.defaultView;
if (unsafeWin.wrappedJSObject) unsafeWin=unsafeWin.wrappedJSObject;
var unsafeLoc=new XPCNativeWrapper(unsafeWin, "location").location;
var href=new XPCNativeWrapper(unsafeLoc, "href").href;
if (
ddplus_gmCompiler.isGreasemonkeyable(href)
&& ( /http:\/\/ddunlimited\.net/.test(href) )
&& true
) {
var script=ddplus_gmCompiler.getUrlContents(
'chrome://ddplus/content/ddplus.js'
);
ddplus_gmCompiler.injectScript(script, href, unsafeWin);
}
},
injectScript: function(script, url, unsafeContentWin) {
var sandbox, script, logger, storage, xmlhttpRequester;
var safeWin=new XPCNativeWrapper(unsafeContentWin);
sandbox=new Components.utils.Sandbox(safeWin);
var storage=new ddplus_ScriptStorage();
xmlhttpRequester=new ddplus_xmlhttpRequester(
unsafeContentWin, window//appSvc.hiddenDOMWindow
);
sandbox.window=safeWin;
sandbox.document=sandbox.window.document;
sandbox.unsafeWindow=unsafeContentWin;
// patch missing properties on xpcnw
sandbox.XPathResult=Components.interfaces.nsIDOMXPathResult;
// add our own APIs
sandbox.GM_addStyle=function(css) { ddplus_gmCompiler.addStyle(sandbox.document, css) };
sandbox.GM_setValue=ddplus_gmCompiler.hitch(storage, "setValue");
sandbox.GM_getValue=ddplus_gmCompiler.hitch(storage, "getValue");
// kick : aggiunta la funzione
sandbox.GM_remove=ddplus_gmCompiler.hitch(storage, "remove");
sandbox.GM_openInTab=ddplus_gmCompiler.hitch(this, "openInTab", unsafeContentWin);
sandbox.GM_xmlhttpRequest=ddplus_gmCompiler.hitch(
xmlhttpRequester, "contentStartRequest"
);
//unsupported
sandbox.GM_registerMenuCommand=function(){};
sandbox.GM_log=function(){};
sandbox.GM_getResourceURL=function(){};
sandbox.GM_getResourceText=function(){};
sandbox.__proto__=sandbox.window;
try {
this.evalInSandbox(
"(function(){"+script+"})()",
url,
sandbox);
} catch (e) {
var e2=new Error(typeof e=="string" ? e : e.message);
e2.fileName=script.filename;
e2.lineNumber=0;
//GM_logError(e2);
alert(e2);
}
},
evalInSandbox: function(code, codebase, sandbox) {
if (Components.utils && Components.utils.Sandbox) {
// DP beta+
Components.utils.evalInSandbox(code, sandbox);
} else if (Components.utils && Components.utils.evalInSandbox) {
// DP alphas
Components.utils.evalInSandbox(code, codebase, sandbox);
} else if (Sandbox) {
// 1.0.x
evalInSandbox(code, sandbox, codebase);
} else {
throw new Error("Could not create sandbox.");
}
},
openInTab: function(unsafeContentWin, url) {
var tabBrowser = getBrowser(), browser, isMyWindow = false;
for (var i = 0; browser = tabBrowser.browsers[i]; i++)
if (browser.contentWindow == unsafeContentWin) {
isMyWindow = true;
break;
}
if (!isMyWindow) return;
var loadInBackground, sendReferrer, referrer = null;
loadInBackground = tabBrowser.mPrefs.getBoolPref("browser.tabs.loadInBackground");
sendReferrer = tabBrowser.mPrefs.getIntPref("network.http.sendRefererHeader");
if (sendReferrer) {
var ios = Components.classes["#mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
referrer = ios.newURI(content.document.location.href, null, null);
}
tabBrowser.loadOneTab(url, referrer, null, null, loadInBackground);
},
hitch: function(obj, meth) {
var unsafeTop = new XPCNativeWrapper(unsafeContentWin, "top").top;
for (var i = 0; i < this.browserWindows.length; i++) {
this.browserWindows[i].openInTab(unsafeTop, url);
}
},
apiLeakCheck: function(allowedCaller) {
var stack=Components.stack;
var leaked=false;
do {
if (2==stack.language) {
if ('chrome'!=stack.filename.substr(0, 6) &&
allowedCaller!=stack.filename
) {
leaked=true;
break;
}
}
stack=stack.caller;
} while (stack);
return leaked;
},
hitch: function(obj, meth) {
if (!obj[meth]) {
throw "method '" + meth + "' does not exist on object '" + obj + "'";
}
var hitchCaller=Components.stack.caller.filename;
var staticArgs = Array.prototype.splice.call(arguments, 2, arguments.length);
return function() {
if (ddplus_gmCompiler.apiLeakCheck(hitchCaller)) {
return;
}
// make a copy of staticArgs (don't modify it because it gets reused for
// every invocation).
var args = staticArgs.concat();
// add all the new arguments
for (var i = 0; i < arguments.length; i++) {
args.push(arguments[i]);
}
// invoke the original function with the correct this obj and the combined
// list of static and dynamic arguments.
return obj[meth].apply(obj, args);
};
},
addStyle:function(doc, css) {
var head, style;
head = doc.getElementsByTagName('head')[0];
if (!head) { return; }
style = doc.createElement('style');
style.type = 'text/css';
style.innerHTML = css;
head.appendChild(style);
},
onLoad: function() {
var appcontent=window.document.getElementById("appcontent");
if (appcontent && !appcontent.greased_ddplus_gmCompiler) {
appcontent.greased_ddplus_gmCompiler=true;
appcontent.addEventListener("DOMContentLoaded", ddplus_gmCompiler.contentLoad, false);
}
},
onUnLoad: function() {
//remove now unnecessary listeners
window.removeEventListener('load', ddplus_gmCompiler.onLoad, false);
window.removeEventListener('unload', ddplus_gmCompiler.onUnLoad, false);
window.document.getElementById("appcontent")
.removeEventListener("DOMContentLoaded", ddplus_gmCompiler.contentLoad, false);
},
}; //object ddplus_gmCompiler
function ddplus_ScriptStorage() {
this.prefMan=new ddplus_PrefManager();
}
ddplus_ScriptStorage.prototype.setValue = function(name, val) {
this.prefMan.setValue(name, val);
}
ddplus_ScriptStorage.prototype.getValue = function(name, defVal) {
return this.prefMan.getValue(name, defVal);
}
ddplus_ScriptStorage.prototype.remove = function(name) {
return this.prefMan.remove(name);
}
window.addEventListener('load', ddplus_gmCompiler.onLoad, false);
window.addEventListener('unload', ddplus_gmCompiler.onUnLoad, false);
The user script is massive and available in this gist.
To be able to see the error:
install the addon
go to the message board at http://ddunlimited.net/
open any thread and open click the reply link
The message will appear as soon as the reply page loads.
in practice is a tool created specifically for a forum ... with the functions targeted to simplify the daily actions of the moderator. Now the forum has changed domain and tried to make it compatible with the new forum. I'm editing the js file with a simple text editor. ettengo the error when I edit the script that I posted above. if you do not touch this script ... some functions disappear and are no longer present.
someone can help me? thank you very much: D
OK, reproducible after all. The error in this case has a bogus message, as this isn't actually an OOM condition, but evalInSandbox() receiving a notification from the JS engine that the script was aborted (due to it being unresponsive) and evalInSandbox() not being able to tell the difference.
The reason is an infinite loop in your code at line 425 (cont.):
var max = textArea.parentNode.parentNode.clientHeight;
while (max == textArea.parentNode.parentNode.clientHeight)
textArea.rows++;
This loop whill never abort as the condition will never get false.

Modify collapse.js to get addtional data from xml when expanding fieldset in Drupal 7?

In drupal i have generated a list where each item is a fieldset with collapsible, that can contain extra information.
Because of the rather large list i want to avoid loading the extra information until a user clicks on the fieldset.
Best case scenario:
User clicks on collapsed fieldset.
Fieldset loads extra information.
Fieldset uncollapses.
I've copied and loaded the copy of collapse.js into my form, but I'm very new to js and jQuery, so I'm a little lost. If someone can show me how to call a function the first time the fieldset is expanded, I'm sure i can figure out the rest.
I've included the code from collapse.js:
(function ($) {
//Toggle the visibility of a fieldset using smooth animations.
Drupal.toggleFieldset = function (fieldset) {
var $fieldset = $(fieldset);
if ($fieldset.is('.collapsed')) {
var $content = $('> .fieldset-wrapper', fieldset).hide();
$fieldset
.removeClass('collapsed')
.trigger({ type: 'collapsed', value: false })
.find('> legend span.fieldset-legend-prefix').html(Drupal.t('Hide'));
$content.slideDown({
duration: 'fast',
easing: 'linear',
complete: function () {
Drupal.collapseScrollIntoView(fieldset);
fieldset.animating = false;
},
step: function () {
// Scroll the fieldset into view.
Drupal.collapseScrollIntoView(fieldset);
}
});
}
else {
$fieldset.trigger({ type: 'collapsed', value: true });
$('> .fieldset-wrapper', fieldset).slideUp('fast', function () {
$fieldset
.addClass('collapsed')
.find('> legend span.fieldset-legend-prefix').html(Drupal.t('Show'));
fieldset.animating = false;
});
}
};
//Scroll a given fieldset into view as much as possible.
Drupal.collapseScrollIntoView = function (node) {
var h = document.documentElement.clientHeight || document.body.clientHeight || 0;
var offset = document.documentElement.scrollTop || document.body.scrollTop || 0;
var posY = $(node).offset().top;
var fudge = 55;
if (posY + node.offsetHeight + fudge > h + offset) {
if (node.offsetHeight > h) {
window.scrollTo(0, posY);
}
else {
window.scrollTo(0, posY + node.offsetHeight - h + fudge);
}
}
};
Drupal.behaviors.collapse = {
attach: function (context, settings) {
$('fieldset.collapsible', context).once('collapse', function () {
var $fieldset = $(this);
// Expand fieldset if there are errors inside, or if it contains an
// element that is targeted by the uri fragment identifier.
var anchor = location.hash && location.hash != '#' ? ', ' + location.hash : '';
if ($('.error' + anchor, $fieldset).length) {
$fieldset.removeClass('collapsed');
}
var summary = $('<span class="summary"></span>');
$fieldset.
bind('summaryUpdated', function () {
var text = $.trim($fieldset.drupalGetSummary());
summary.html(text ? ' (' + text + ')' : '');
})
.trigger('summaryUpdated');
// Turn the legend into a clickable link, but retain span.fieldset-legend
// for CSS positioning.
var $legend = $('> legend .fieldset-legend', this);
$('<span class="fieldset-legend-prefix element-invisible"></span>')
.append($fieldset.hasClass('collapsed') ? Drupal.t('Show') : Drupal.t('Hide'))
.prependTo($legend)
.after(' ');
// .wrapInner() does not retain bound events.
var $link = $('<a class="fieldset-title" href="#"></a>')
.prepend($legend.contents())
.appendTo($legend)
.click(function () {
var fieldset = $fieldset.get(0);
// Don't animate multiple times.
if (!fieldset.animating) {
fieldset.animating = true;
Drupal.toggleFieldset(fieldset);
}
return false;
});
$legend.append(summary);
});
}
};
})(jQuery);
It looks to me like you'd have to override the whole Drupal.toggleFieldset function (just like when you are overriding a Drupal theme function.
You could perhaps add a class to the fieldset in FormAPI then catch it in the complete function of the $content.slideDown params and fire a custom function of yours, to add a 'loading' graphic and make your ajax request.
I'm assuming from your question that you are familiar enough with FormAPI/jQuery.ajax() to have a go. But let me know if not and i'll include some snippets
EDIT
Here is some example code, it'd take a quite a while to setup a test environment for this, so it'just a pointer (cant create a JS fiddle for this ;))
You might add your fieldset like this in PHP
$form['my_fieldset'] = array(
'#type' = 'fieldset',
'#title' = t('My fieldset'),
'#collapsible' = true,
'#collapsed' = true,
'#attributes' => array(
'class' => array('ajax-fieldset'),
'rel' => 'callback/url/path' // random attribute to store the link to a menu path that will return your HTML
)
);
$form['my_fieldset'] = array(
'#markup' => '<div class="response">loading...</div>'
);
You'll also obviously have setup a menu hook returning your themed data # callback/url/path. IMO it's better to return JSON data and theme them in with JS templating, but the Drupal way (for the moment at least) seems to be to render HTML in the menu hook callback function.
Then here is the JS. I've only included the altered complete function, rather than reproduce what you pasted. Add the complete function in to a copy of the code the re-specify the core Drupal function in your own JS file
$content.slideDown({
complete: function () {
Drupal.collapseScrollIntoView(fieldset);
fieldset.animating = false;
if($fieldset.hasClass('ajax-fieldset')) {
$.get(
Drupal.settings.basePath + $fielset.attr('rel'),
function(data) {
$fieldset.find('.response').html(data);
}
)
}
}
});
Or, rather than messing around with the collapsible function. just create your own fieldset without the collapsible/collapsed classes and implement from scratch yourself
....so.. something like that :)

Profiling jQuery, how do I make my app more snappy?

I have some calls to jQuery functions like 14,000 times... what the hell? I don't have that many functions, really just simple stuff like appending and removing DOM elements, why do some of my event handlers call functions so many times?
Plus to compound my issues, Firebug's profiler just show's the min'd functions names... and even when I use the uncompressed library it mostly just shows init() or $.()
Does anyone have any tricks?
So I know this is a lot, but it seems really inefficient, it executes on our page newgoldleaf.com, some of the functions take almost 50ms to run... is that a long time or is it just me?
// prepare ajax for form posts
jQuery.ajaxSetup({
"beforeSend" : function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
})
// initializes panels and gets url hash, shows correct panel
jQuery.fn.initPanes = function() {
$("div#main_content > div:not(.message)").addClass("inactive");
var hash = window.location.hash.substr(1);
this.each(function () {
if ($(this).hasClass(hash)) {
var panelToShow = "." + $(this).attr("class");
$(panelToShow).removeClass("inactive").toggleClass("active");
}
});
// if no hash found in url, activate first menu item
if (hash == "" ) {
$(this).eq(0).activatePane();
}
};
// shows panel when user clicks sidebar links
jQuery.fn.activatePane = function(pane) {
if ($(this).hasClass("unavailable") == true) {
return false;
}
if ($(this).hasClass("active") == false) {
$("div#main_content > div:not(.message)").hide().removeClass("active").addClass("inactive");
$(this).siblings().removeClass("active");
var panelToShow = "div#main_content div." + $(this).attr("class");
// set the hash in the url
window.location.hash = $(this).attr("class");
$(this).toggleClass("active");
$(panelToShow).fadeIn("slow").removeClass("inactive").addClass("active");
};
};
jQuery.fn.functionName = function() {
};
$(document).ready(function (){
$('ul.examples li:not(img, h5, a)').hover(function (){
var bubble = $(this).find("h5.bubble")
bubble.animate({
opacity:".99",
bottom:"28px"
}, 200);
}, function (){
var bubble = $(this).find("h5.bubble")
bubble.animate({
opacity:"0",
bottom:"38px"
}, 200).animate({
bottom:"20px"
}, 0);
});
// hide/show comment form for users with javascript
$("div#comments_not_allowed").hide();
$("form#new_comment").show();
// $("body#index div.preview").slideShow();
// error and flash notice animation
$(".message").animate({
opacity: "1",
}, 2000).animate({
opacity: "0",
}, 2000).hide(500);
// home page caption bubble for blog image fade in
$("body#index h5.bubble").fadeIn("slow");
$("body#index h5.bubble").animate({
bottom: "22px",
opacity: ".99"
}, 1000);
$("form#new_comment").submit(function() {
$.post($(this).attr("action"), $(this).serialize(), null, "script");
return false;
});
$("form#new_lead").submit(function() {
$.post($(this).attr("action"), $(this).serialize(), null, "script");
return false;
});
if ($("ul.panels").length > 0 ) {
// panel animation
$("div#aside ul li").initPanes();
$("div#aside ul li").css({
cursor:"pointer"
});
$("div#aside ul li").click(function () {
$(this).activatePane();
});
};
$(document).load(function() {
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
function startAnalytics() {
var pageTracker = _gat._getTracker("UA-7434953-1");
pageTracker._initData();
pageTracker._trackPageview();
}
if (window.addEventListener) {
window.addEventListener('load', startAnalytics, false);
}
else if (window.attachEvent) {
window.attachEvent('onload', startAnalytics);
}
})
})

Categories

Resources