Using only jQuery and CiviCRM to create Members Only Pricing

Pubblicato
2012-02-13 19:44
Written by
Stoob - member of the CiviCRM community - view blog guidelines

There have been several hook() or Drupal module based solutions for "members only" pricing for events or for other 'discounts' related to memberships.

 

I take a different approach by using only jQuery and blocks in Drupal 6.  For those who use Drupal 7 you can adapt this code with Drupal 7's new javascript namespace and Joomla folks could even make use of this in custom TPL files.

 

The whole concept of this code is that any 'member only' fee label must contain a specific word or phrase, in my example this word is "Member".  Staff must be trained to do this - it is relatively simple to do so.

 

How it works:

1. Place this code in a block, selecting "full HTML" or "unfiltered" input type, and assign the block to an inconspicuous region in your theme

2. Show the block only on certain pages, such as: civicrm/event/register

3. Show the block only to anonymous users in the block visibility settings

 

That's it!  Fee levels containing the word "Member" will be hidden.

<script>
cj(document).ready(function() {
    cj("input[name=amount]").each(function() {
      var thisPrice = cj(this).attr('id');
      cj("label[for='"+thisPrice+"']:contains('Member')").hide();
      cj("label[for='"+thisPrice+"']:contains('Member')").prev("#"+thisPrice).hide();
    });
});
</script>

Ways you can customize and enhance this

1. Change the word "Member" to a phrase of your choosing

2. Hide only the radio button, not the label, to 'entice' people to join. Delete the first line with hide() at the end

3. Activate this code only on certain pages by placing the unique id of the page in the if() statement near the top. That would look like this:

<script>
cj(document).ready(function() {
// add the id numbers of the pages you want below
if ( 
  document.location.href.indexOf('id=1') > 0 ||
  document.location.href.indexOf('id=2') > 0 ) {	
    cj("input[name=amount]").each(function() {
      var thisPrice = cj(this).attr('id');
      cj("label[for='"+thisPrice+"']:contains('Member')").hide();
      cj("label[for='"+thisPrice+"']:contains('Member')").prev("#"+thisPrice).hide();
    });
  }
});
</script>

4. Show the member pricing not simply to authenticated users, but to only users who are memembers

  • Activate the CiviMember > Roles Sync script
  • Change the visibility settings of the first block to be seen by all, thus hiding member pricing for everyone
  • Make a second block with visibility settings only for your exclusive Member > Roles
  • Copy and paste the same code, but change hide() to show(), thus re-showing member prices only to members
  • Place this second block just below the first block

Comments

Hi,

 

That's a nice trick, but keep in mind that it wouldn't stop any anonymous visitor to "hack" and choose the members only anyway (eg. if you disable javascript).

 

If security is needed (probably not a big deal in your case), then you'd need to add hook on the server to double check that no non member has chosen a member price.

 

Thanks for sharing

X+

That's correct.  Absolute security of 'members only' pricing isn't a concern in my application.  Non-members are aware that members get a discount, we just don't want non-members to be presented with an option for a discount and have them select it by mistake.  We will spot check any event participants for valid memberships.

That module plus one other random post I found via Google (link now lost to time-space) was all I have.  Sorry if you feel I didn't give your module a try, but when I saw Civi3.3 was the highly recommended version, I moved on.  Upgrading to 4.1 will be just around the corner, and I wanted a lightweight solution that could be used with 4.1, adapted to D7, and used with Wordpress in conjunction with Widget Logic plugin.   Security and the fuller features of your module aren't necessary in my cases.  Your module does sound cool though.  Thanks.

For me, it's easy D7 support... I have yet to find something I can use as a non-coder. All the options I've seen are for D6.

I'd use the code above, but I don't have the chops to convert the above code D7 compatible... maybe someone would perform that small act of kindness for me and others?

 

 

 

There is an MIH to make modules CMS agnostic (so will include D7 and wordpress). Its quite close to being fulfilled:

http://civicrm.org/participate/mih#cmsagnostic

Help make it happen

lobo

Very true while using wordpress platform MIH module will be better option even its good for Joomla.

Bayside lounge

Modified code for Drupal 6 and CiviCRM 4.1.2. The above code did not work for some reason. Note, it only works right now with radio and checkbox fields.

 

Block 1 has visibility for anonymous users. It removes all pricing options with word 'Member' in them. In effect, anonymous people don't get member pricing.

 

<script>
cj(document).ready(function() {
       //Find all labels containing the text 'Member' that are descendants of the element with id 'priceset'
     cj("#priceset").find("label:contains('Member')").each(function() {
               //Get the value of this labels for attribute. 
               var id = cj(this).attr('for');
               //If it has a value, this is one we want to remove
               if (id) {
                       //Remove the previous element which we know is an input
                   cj(this).prev().remove();        
                   //Remove this element as well
                   cj(this).remove();
       }
       });
});
 
</script>
 
Block 2 has visibility for Members (Members Role, sycned to Drupal user from CiviCRM). It hides all options that don't have word "Member" present. This in effect shows only Member-pricing for Members. The opposite of Block 1.
 
<script>
 
cj(document).ready(function() {
       //Find all labels containing the text 'Member' that are descendants of the element with id 'priceset'
      cj("#priceset").find("label:not(:contains('Member'))").each(function() {
               //Get the value of this labels for attribute. 
               var id = cj(this).attr('for');
               //If it has a value, this is one we want to remove
               if (id) {
                       //Remove the previous element which we know is an input
                   cj(this).prev().remove();        
                   //Remove this element as well
                   cj(this).remove();
       }
       });
});
 
</script>
 
Also, for those new to CiviCRM and jQuery, cj is a renamed jQuery object so it does not conflict with Drupal's jQuery. 
 
This code was developed by Corey Sunwold, http://coreysunwold.com/

 

Here's the code for the anonymous block modifided for Drupal 7. I added in a bit to remind users to login to get their member price

<script type="text/javascript">

    (function($) {

    $(document).ready(function() {


//This is our custom jQuery code

   

$("#priceset").find("label:contains('Members')").each(function(){

            var id = $(this).attr('for');

            if (id) {

                $(this).prev().remove();

                $(this).remove();

                    }

            });

    $("#priceset").prepend("<h3>If you are a member, log in for member prices</h3>");

//This is the end of our custom jQuery code

  }); 

  }) (jQuery);

</script>