Skip to main content

GROWING AND SUSTAINING RELATIONSHIPS

GROWING AND SUSTAINING RELATIONSHIPS
Close
Michael Daryabeygi

Implementor

Ginkgo Street Labs

http://ginkgostreet.com

CiviCRM enables me to empower my clients with a database that suits their unique needs.

GROWING AND SUSTAINING RELATIONSHIPS
Close
Arthur Richards

DEVELOPER

WIKIMEDIA FOUNDATION

http://wikimediafoundation.org

At the Wikimedia Foundation, we leverage CiviCRM to maintain millions of records of donors and their contributions. Working with the product and particularly with the community has been a terrific experience. There's nothing quite like two open source organizations working together to meet their respective goals while ultimately strengthening the open source community as a whole.

GROWING AND SUSTAINING RELATIONSHIPS
Close
Abril Rocabert

Administrator and End-user

http://www.alternativasycapacidades.org

CiviCRM is a powerful tool that could be really useful for many non-profits in Mexico.
Unfortunately the community is very small in my country. I hope that in the next years the community expands around Latin America.

GROWING AND SUSTAINING RELATIONSHIPS
Close
Paul Keogan

Implementor

BackOfficeThinking

http://www.backofficethinking.com

CiviCRM allows us to bring all benefits and capabilities of a large commercial CRM and
donor management system to medium and large non-profits at a fraction of the cost. CiviCRM also allows smaller non-profits to benefit from an integrated solution for donor management, events, bulk email, etc. substantially increasing their effectiveness as compared to managing a variety of nonintegrated software and spreadsheets. Thanks to a strong CiviCRM community, CiviCRM’s functionality continues to advance and CiviCRM’s market continues to grow rapidly.

GROWING AND SUSTAINING RELATIONSHIPS
Close
Adam Wight

Developer

Giant Rabbit

http://giantrabbit.com/

Saves us from writing monstrous, custom database apps.

GROWING AND SUSTAINING RELATIONSHIPS
Close
Allen Gunn

Ally, FanBoy

Aspiration

http://aspirationtech.org/

By giving the nonprofit sector a values-driven, free/open source solution for CRM needs!

GROWING AND SUSTAINING RELATIONSHIPS
Close
Peter McAndrew

Implementor, Developer

Third Sector Design

http://www.thirdsectordesign.org

Being part of the CiviCRM community is really something to shout about! Not only is CiviCRM an amazing software package, its designed for organisations that make a difference in the world. We help non-profits across the UK gain control of their data through the power of CiviCRM.

It is without a doubt the best piece of software I've ever worked with, and I'm constantly discovering cool new features. More recently I've been working on CiviMobile as part of a project for my course at University. I'm really looking forward to seeing this being used by organisations across the globe.

GROWING AND SUSTAINING RELATIONSHIPS
Close
Alice Aguilar

Implementor

Progressive Technology Project

http://progressivetech.org

The organizations we work with are experiencing the benefits of a robust tool that is
easy to use, supports their work, and allows them to collect and track data from various parts of their organization, such as membership, fundraising, communications, and organizing into a centralized database. CiviCRM as an open-source solution also allows us to nurture and build a user community to share and create a common vision of future features that would be useful to the community organizing field. Just two years after our pilot project, we're currently supporting 30 community organizing groups to use CiviCRM, and the community is steadily growing.

GROWING AND SUSTAINING RELATIONSHIPS
Close
Amy Bucaida

Administrator

Missouri Credit Union Association

http://www.mcua.org

We are a full CiviCRM install with Drupal.

GROWING AND SUSTAINING RELATIONSHIPS
Close
Kellie Brownell

End-user

EFF

https://www.eff.org

The CiviCRM community has been a tremendous resource for new ideas and helping us solve problems. We are excited to contribute customizations EFF makes back to core and support new features such as batch entry for offline donations or multiple payment processors on one donation form.

GROWING AND SUSTAINING RELATIONSHIPS
Close
David Moreton

Consultant

Circle Interactive

http://www.civisites.com

We help many not for profits implement CiviCRM through consultancy, training, configuration and custom development. Many of them come from a painful world of old Access databases, multiple spreadsheets and even paper. It's really satisfying to
help people move on with a system that's so much in tune with their own ethics of sharing and collaboration. We also 'eat our own dog food' and use Civi in-house for our client records because we love the flexibility and control it gives us.

For us it's important to share code and advice with other members of the community when we can because we know we get it back in help at other times. The community really is awesome and one of the friendliest and undaunting I've come across. We appreciate the huge value of the software to us and our clients so we try to contribute back and make it even better.

GROWING AND SUSTAINING RELATIONSHIPS
Close
Erik Hommel

Implementer, Developer

EE-atWork

The CiviCRM community is a very friendly and helpful community. Whatever the challenge, I always get enough help from the forum or IRC to nudge me in the right direction. For me joining in a CiviCRM sprint once or twice a year is the best, meeting other community members in real life, sharing successes, challenges, problems and meals :-) Seriously, I think the active community is one of the serious assets of CiviCRM and I am proud to be part of it! And when I grow up I promise to do more :-)

LOGIN | REGISTER
  • Create new account
  • Request new password

Search form

  • BLOG
  • DEMO
  • Find An Expert
  • NEED HELP
  • SUPPORT US
  • DEVELOPER RESOURCES
CiviCRM Community Site logo CiviCRM Community Site
  • WHAT IS CIVICRM
    • Community
    • Case Studies
    • Experts
    • Contributors
    • Core Team
    • Licensing
    • Contact Us
  • WILL CIVICRM MEET YOUR NEEDS?
    • Contacts
    • Contributions
    • Communications
    • Peer-To-Peer Fundraisers
    • Advocacy Campaigns
    • Events
    • Members
    • Reports
    • Case Management
  • GET STARTED
    • Evaluate Your CRM Needs
    • Evaluate CiviCRM Features
    • Read Books
    • Demo CiviCRM
    • Download CiviCRM
    • Find An Expert
  • PARTICIPATE
    • Join the CiviCRM Community
    • Read Our Blog
    • Community Forum
    • Attend a Training or Meetup
    • Make It Happen
    • Contribute
    • Become A CiviCRM Developer
    • Issue Tracker
    • Help with Documentation
    • Translate

You are here

Home » Blogs » hershel's blog

Blog

  • Architecture Series
  • CiviCampaign
  • CiviCase
  • CiviCon
  • CiviContribute
  • CiviCRM
  • CiviCRM API
  • CiviCRM Code Sprint
  • CiviCRM Meetups
  • CiviCRM Release
  • CiviCRM Solutions (case studies and user stories)
  • CiviCRM Team
  • CiviCRM Training
  • CiviCRM v1.6
  • CiviCRM v1.7
  • CiviCRM v1.8
  • CiviCRM v1.9
  • CiviCRM v2.0
  • CiviCRM v2.1
  • CiviCRM v2.2
  • CiviCRM v2.3
  • CiviCRM v3.0
  • CiviCRM v3.1
  • CiviCRM v3.2
  • CiviCRM v3.3
  • CiviCRM v3.4 and v4.0
  • CiviCRM v4.1
  • CiviCRM v4.2
  • CiviEvent
  • CiviMail
  • CiviMember
  • CiviMobile
  • CiviPledge
  • CiviReport
  • Documentation
  • Drupal
  • Extensions
  • Finance and Accounting
  • Interface Design and Layout Standards
  • Internationalization and Localization
  • Joomla
  • Older Versions
  • Schools
  • WordPress

How to Customize CiviCRM Pages with jQuery

Submitted by hershel on April 4, 2011 - 10:57

There are three ways one can customize the look of CiviCRM pages:

  1. Customizing CiviCRM templates
  2. Custom CSS in a Joomla! template or Drupal theme
  3. Custom jQuery code

In this post we will review them and provide a few examples of the most complicated method, jQuery manipulation.

Customizing CiviCRM templates

This method is described in depth on our wiki under Theming CiviCRM and the subpages therein.

The advantage of this method is that it is fairly easy to make simple changes. The disadvantage is that upgrades may significantly change the core templates and thus require one to redo the customizations “from scratch."

Custom CSS in a Joomla! template or Drupal theme

If your site uses a custom template or theme, then using normal CSS rules, one can fairly simply override the core CiviCRM CSS rules and replace them with your own custom ones.

The advantage of this method is that it is fairly easy to make simple changes. I am not aware of any particular disadvantages of this method and in fact whenever it's feasible, this is the method I would recommend.

Custom jQuery code

There are some customizations which can not be done via CSS, or which can be done via a custom CiviCRM template, but are quite difficult and there are others which are simply impossible to do purely via a CiviCRM template change. In many instances, however, such customizations can be safely implemented via jQuery.

The first step is to put a jQuery file onto your site. For Joomla! sites see Adding Javascript and for Drupal sites see Adding JavaScript to your theme or module and Working with JavaScript and jQuery. There may be other ways to add a JS file to a Joomla! site and it may be possible to achieve the functionality described below with Mootools (which ships with Joomla!). I will leave it up to any Joomla! or Mootools gurus to add their replies regarding such below.

Once the file is added to the site, now we just put in it whatever DOM manipulation we want. We will examine a few examples here and the concept will hopefully be clear.

Let's start with a simple example. If one has an event page with a long text and map etc. the “Register Now" button may only be found after scrolling down a bit. If a user comes to the page already intending to register, it would be easier for him to have that button right at the top of the page. To move this button we simply use Firebug in Firefox to find the ids or classes of the relevant items, in this case, the button itself and the event description section at the top. Then we move the button like this:


if (Drupal.jsEnabled) {
$(document).ready(function () {
$('div.event_description-section').prepend($('div.register_link-section'));
});
}

In actuality only the middle line interests us, because the rest is just a wrapper to have the code executed in the correct environment. We will focus now on just that code, which is what does the work. This one line is not actually correct, however, because while it did put a button at the top, it removed the button from the bottom and really is the equivalent of this line, i.e. with the remove function:


$('div.event_description-section').prepend($('div.register_link-section').remove());

What we want is to clone the button so that it's at both locations. Luckily jQuery has precisely such a function and so with this:


$('div.event_description-section').prepend($('div.register_link-section').clone());

We now have exactly what we want—two Register Now buttons, one at the top and one at the bottom of the page.

For a second, more complicated, examle, let's imagine an NPO which works with addiction therapy. We have a custom tab for Contacts with a checkboxes called “Alcohol" and “Crack" etc. which are meant to indicate whether or not the Contact has these addictions. After each is a date field to store when he began that addiction. With no customization, here is how the fields look:

If this were a real site, however, the list of substances would be much longer. It would be easier to read and use if the date fields could be to the right of the checkboxes. It would be even clearer if we could hide those date fields which are not relevant, i.e. where the checkbox is not checked. This type of customization is well-suited for jQuery.

The first step here is to find how to target the DOM elements and then move them. Using Firebug, we can find that the classes assigned to the “Crack" row are “custom_field-row custom_256_155-row" It is tempting to therefore use the class “custom_256_155-row" as our selector. If we load up a few other contacts, however, we will eventually find that whereas the 256 number remains the same (as that is the ID of the custom field) the 155 number changes with each contact. So our actual selector is “custom_256_*" where the * is a wildcard. The way to target a class with a wildcard such as that is with this:


$("tr[class^=custom_field-row custom_256_]")

which means any TR with a full class definition starting with “custom_field-row custom_256_". Now that we have targeted our first row, we can add a TABLE tag onto the second TD tag, which sets up a container to use to relocate our date row. Now we remove our date row, which is id 257 in this case, from the main table and append it to our new table. This is half the job (for this one substance anyhow) and is the first two lines in the code below.

The second half of the job is to add an onclick handler to hide or show the date field depending on the state of the addiction checkbox. To do this, we use the same row target method to target our input and then add a fairly simple click handler. Here is the full code:


$("tr[class^=custom_field-row custom_256] .html-adjust").append('

');
$("tr[class^=custom_field-row custom_256_] table").append($('tr[class^=custom_field-row custom_257_]').remove());
$("tr[class^=custom_field-row custom_256_] input").click(function(){
if ($(this).attr('checked')) {
$(this).parent().parent().find('table').show();
}
else {
$(this).parent().parent().find('table').hide();
}
})

Here is how the fields look afterward, with the Crack date hidden after we clicked it to be not checked:

The truth is that this is not a complete solution, because when the page loads, the code needs to check the status of the checkbox and hide the date field if necessary. Furthermore, this solution is specific to only one substance and needs to be generalized for a list of them. One could also use the toggle function instead of hide and show. The basic ideas required, however, are above and the savvy developer can expound upon them for a full solution. :)

  • hershel's blog
  • Log in or register to post comments

Comments

Nice wrap up

Permalink Submitted by xavier on April 4, 2011 - 11:15

Hi,

Like your regex trick: tr[class^=custom_field-row custom_256]. Was doing a loop on the items to find the one I wanted, what you are suggesting is nicer.

 

For everyone, I'd suggest learning firebug to help you find the class/id of the items you want to manipulate if you aren't using it already.

 

In the templates, we have tried to give unique names or classes to most of the elements so it's easier to target the right elements. Some are still missing probably, but if you happen to need one id or class missing, you can fill an issue (with a patch will be faster) and we'll fix it.

 

Hertzel, for the events you are organising, is this necessary to use both crack and alcohol or one is enough to be invited to the party :) ?

 

X+

  • Log in or register to post comments

Hi, I struggle with JQuery /

Permalink Submitted by Eileen on April 4, 2011 - 14:09

Hi, I struggle with JQuery / js so this is great. When I did need to do something by js I followed a recommendation by Denver Dave to use   drupal_add_js

 

I'm interested in your opinion as to where this 4th option sits compared to #3

 

My function - just populates a custom field calculated off amount & another custom field

 

function mymodule_civicrm_buildForm( $formname, $form ){

if ($formname == 'CRM_Pledge_Form_Pledge'){
   if($_GET['id']){
     $instance = $_GET['id'];
   }else{
     $instance ='-1';
   }
   $jqueryinsert = "
      cj(document).ready( function() {
      cj('#amount').blur(function(){
        if(cj('#amount').attr('value') > 0){
        var newValue = cj('#custom_57_$instance').attr('value') *.05 / cj('#amount').attr('value') * 100;
         cj('#custom_207_$instance').val(newValue);
         }
        
      });
});
";
   drupal_add_js( $jqueryinsert , 'inline');

}

 }

  • Log in or register to post comments

I would appear to me that

Permalink Submitted by hershel on April 4, 2011 - 17:43

I would appear to me that this is simply a different way to get the jQuery code onto the page, and thus falls into my #3 actually. :)

It would further appear that if your jQuery used the wildcard method (instead of $instance), this code could be in a file, not inline, and thus not require backend processing, and could also be cached along with other JS code.

  • Log in or register to post comments

Cool. Thanks for that

Permalink Submitted by Eileen on April 4, 2011 - 18:06

Cool. Thanks for that feedback

  • Log in or register to post comments

The disadvantage is that

Permalink Submitted by dalin on April 4, 2011 - 22:54

The disadvantage is that upgrades may significantly change the core templates and thus require one to redo the customizations “from scratch."

To ease this headache I always put notes at the top of each custom template about what was changed.

$("tr[class^=custom_field-row custom_256_]")...

This is an incredibly inefficient line of jQuery. Run this on IE6 and it might take seconds to execute. It would be better to use a containing ID first:

$("#some-id").find("tr[class^=custom_field-row custom_256_]").each(function(){ 

  $(this).find("table")... 

});
 

Better yet to try and split out the .custom_field-row before you do the regex for greater resistance to DOM changes.

 

 

  • Log in or register to post comments

Making IE6 users waiting

Permalink Submitted by xavier on April 5, 2011 - 00:11

Is more a positive point than a negative one, isn't it ? For those 1% that haven't upgraded, let's push them to do it (or better yet to switch to an open source browser). In this day and age, when even microsoft has stopped supporting ie6 for like 2 years, we really shouldn't take care about it anymore.

 

But you are right, setting a parent will speed up things a bit

instead of

$("#some-id").find("tr[class^=custom_field-row custom_256_]").each(function(){

$("#some-id tr[class^=custom_field-row custom_256_]").each(function(){
is more readable

Unfortunately in this case, don't think we have an id set by civi above, so we depend on the theme.
$("form tr[class^=custom_field-row custom_256_]").each(function(){

Is probably going to work and be as fast as a #some-id

Anyway, on any sane browser, that's probably going to save a few ms when you load the registration form.

X+

 

  • Log in or register to post comments

If only...

Permalink Submitted by davej on April 13, 2011 - 03:16

Sadly IE6 still has around 4% share and even more sadly, it's widely used in the public sector in the UK, including the National Health Service - Europe's largest employer - and the Ministry of Defence. We have health sector clients so we have to support it. But its days in the NHS may be numbered.

 

  • Log in or register to post comments

How do you work with something that has other jQuery targeting?

Permalink Submitted by malks on April 6, 2011 - 18:29

Hi,

 

Thanks for the blog.  I've asked the question below in the forum, but it was relevant to this discussion so I hope you don't mind me asking it here.

 

How does this work when you want to modify something that seems to have other jQuery affecting it?  I'm trying to get an autocomplete (assigned to on activity) pre populated with the logged in user, but I can't seem to do anything on it as it starts life as an input that is changed to a ul.  I think I need to get my javascript to load later than the autocomplete java?  Have you seen this sort of requirement before?

 

Thanks,

Malks.

  • Log in or register to post comments

Hi. I found your forum post

Permalink Submitted by hershel on April 7, 2011 - 10:11

Hi. I found your forum post but beyond the ideas presented there, I don't know how possible this is. However you could certainly (I think) adjust the autocomplete code in the CiviCRM templates to call a function after converting the input.

 

That would be method #1 described above. It also has a place. :)

  • Log in or register to post comments

Drupal/Joomla jQuery versus Civi jQuery

Permalink Submitted by davej on April 13, 2011 - 02:46

Thanks for this useful post. Is there a reason to use jQuery from Drupal/Joomla rather than Civi's jQuery, cj() ?

  • Log in or register to post comments

jQuery not in a template

Permalink Submitted by Max Bronsema (not verified) on May 6, 2011 - 09:01

Hi Hershel,
Thank you for the great writeup on implementing jQuery within Civi. I am trying to use jQuery loaded via a module .info file, to set some default values on a form. However, even though the jQuery is loaded, and no errors are triggered nothing happens. To begin with, to verify jQuery is working properly I am trying to simply remove a class from the New Case screen.
if (Drupal.jsEnabled) {
$(document).ready(function () {
$("#profiles_1").removeClass("form-select");
});
}

The above snippet does not remove the class as I would expect it too. Does Civi implement only a subset of the core jQuery functionality? Thanks again for the great introductory post.

  • Log in or register to post comments

here's a little example for code to hide a contribution amount

Permalink Submitted by Stoob on June 23, 2011 - 12:38

This jQuery does 3 things: Hides the radio button of a contribution amount, hides the label, and hides the BR tag immediately after the label.

$("#YOUR_CIVICRM_QFID_999_9").hide();
$("label[for='YOUR_CIVICRM_QFID_999_9']").next('br').remove();
$("label[for='YOUR_CIVICRM_QFID_999_9']").hide();

Put in on your page using one of the methods Hershel lists above.

  • Log in or register to post comments

How to Customize CiviCRM Pages with jQuery

Permalink Submitted by fredie on April 12, 2012 - 09:16

For an event and / or profile registration page, exactly where would the jQuery code to customize the form be placed? I'm very new to CiviCRM and I haven't quite figured out the flow of page, and what goes where. Thanks...fred

  • Log in or register to post comments

What about livequery?

Permalink Submitted by jakecivi on April 19, 2012 - 11:30

I wonder, in pages like the Configure Event -> Fee tab, where it loads the contents of the tabbed page area after the page itself, and therefore after any javascript added by drupal_add_js, how do I change things loaded in the tabbed area? It seems that I'd need to load a copy of livequery, which I've done using drupal_add_js, but then I don't know where to go from there, because neither accessing civicrm's copy of jquery like cj('#selector').livequery(function() {....}); nor accessing Drupal's copy of jquery like $('#selector').livequery(function() {....}); has any effect. Anyone know where to go from here?

  • Log in or register to post comments

Here's a solution from the

Permalink Submitted by jakecivi on April 24, 2012 - 14:16

Here's a solution from the forum where I asked the same question (http://forum.civicrm.org/index.php/topic,24367.msg102482.html#msg102482) :
"You might want to delay where the init code is loaded (eg. on the load instead of the ready event) or wait on an event that is linked to the content you want to alter (with the .on method, you can watch more or less everything, including inserting elements in the dom)"

  • Log in or register to post comments

CIVICRM


GROWING AND SUSTAINING RELATIONSHIPS

WHAT IS CIVICRM
  • Community
  • Case Studies
  • Experts
  • Contributors
  • Core Team
  • Licensing
  • Contact Us
WILL CIVICRM MEET YOUR NEEDS?
  • Contacts
  • Contributions
  • Communications
  • Peer-To-Peer Fundraisers
  • Advocacy Campaigns
  • Events
  • Members
  • Reports
  • Case Management
GET STARTED
  • Evaluate Your CRM Needs
  • Evaluate CiviCRM Features
  • Read Books
  • Documentation
  • Demo CiviCRM
  • Download CiviCRM
  • Find An Expert
PARTICIPATE
  • Join the CiviCRM Community
  • Read Our Blog
  • Community Forum
  • Attend a Training or Meetup
  • Make It Happen
  • Contribute
  • Become A CiviCRM Developer
  • Issue Tracker
  • Help with Documentation
  • Translate