Support Center

Creating an Advanced Widget

Last Updated: Nov 13, 2014 12:16PM PST
In continuation of the Creating a Simple Widget tutorial, we will be looking at an advanced tutorial where we will create a widget that is available through the widget editor.

In this tutorial, our widget (e.g., Feedback Form) will allow a LiveWhale user to overwrite a form's title, intro text, and the drop-down options.

Let's get started.

Step 1. Create a folder in /livewhale/client/modules with the name of your new module. Since our example module is "Feedback Form", we will name the directory, feedback_form.

Step 2. We will add a widget file to the newly created directory, /livewhale/client/modules/feedback_form. The filename must match the appropriate naming conventions. In this case, our module, Feedback Form, will have this filename: public.widget.feedback_form.php

Let's go through the structure of public.widget.feedback_form.php

First, we must register our widget in the CMS

The first code block below will register our widget module. Remember, it is important to follow the naming conventions where 'feedback_form' is where you should match your module name.
 

<?php
  $_LW->REGISTERED_WIDGETS['feedback_form']=array( // add the feedback form widget
        'title'=>'Feedback Form', // the widget's name
        'handlers'=>array('onLoad', 'onDisplay'), // add the widget function handlers
        'widget'=>array( // base configuration settings
                'args'=>array('title', 'intro', 'reason') // keep track of all args offered by this widget
        ),
        'custom'=>array( // custom defaults for this widget
                'default_title'=>'Send us Feedback',
                'default_intro'=>'Please fill out the form below and click submit.',
                'default_reasons'=>array(
                        'Love the site!',
                        'Found a problem',
                        'Need help with widgets'
                )
        )
  );

Next, we need to define our widget class and write our function handlers that we defined in our registration above (onLoad, onDisplay).
 

class LiveWhaleWidgetFeedbackForm { // the feedback form widget class

 // initializes the widget
 public function onLoad() { 
   global $_LW;
  // if there was a feedback form submission
   if (!empty($_LW->_POST['is_feedback_form'])) { 
        sleep(1); // sleep for 1 second before processing 
        
        // if all required fields are completed
        if (!empty($_LW->_POST['name']) && !empty($_LW->_POST['email_address']) && !empty($_LW->_POST['reason']) && !empty($_LW->_POST['comments'])) { 
                // if valid email address
                if (preg_match('~^[A-z0-9_\-.]+[@][A-z0-9_\-]+([.][A-z0-9_\-.]*)+[A-z]{2,4}$~', $_LW->_POST['email_address'])) {
                        // connect to your database and save the submission
                        // give success message
                        die(json_encode(array('success'=>'Your feedback has been received, thank you!'))); 
                }
                else { 
                        // else give validation error
                        die(json_encode(array('error'=>'You must enter a valid email address to give feedback.')));
                };
        }
        else { 
                // else give validation error
                switch(true) {
                        case (empty($_LW->_POST['name'])):
                                die(json_encode(array('error'=>'You must enter your name to give feedback.')));
                                break;
                        case (empty($_LW->_POST['email_address'])):
                                die(json_encode(array('error'=>'You must enter your email address to give feedback.')));
                                break;
                        case (empty($_LW->_POST['reason'])):
                                die(json_encode(array('error'=>'You must enter a reason to give feedback.')));
                                break;
                        case (empty($_LW->_POST['comments'])):
                                die(json_encode(array('error'=>'You must enter your comments to give feedback.')));
                                break;
                };
        };
     };
   }

 // displays the feedback form
  public function onDisplay() { 
   global $_LW;
   $output=''; // initialize the output
   
   // load the templated feedback form (must be valid XHTML)
   if ($template=@file_get_contents($_LW->INCLUDES_DIR_PATH.'/client/modules/feedback_form/includes/template.html')) { 
   
           // set the form title from the "title" arg, or else fall back on the widget default
           $title=(!empty($_LW->widget['args']['title']) && !is_array($_LW->widget['args']['title'])) ? $_LW->widget['args']['title'] :
            $_LW->REGISTERED_WIDGETS['feedback_form']['custom']['default_title']; 
        
        // set the form intro from the "intro" arg, or else fall back on the widget default
        $intro=(!empty($_LW->widget['args']['intro']) && !is_array($_LW->widget['args']['intro'])) ? $_LW->widget['args']['intro'] : 
            $_LW->REGISTERED_WIDGETS['feedback_form']['custom']['default_intro']; 
        
        
        // ensure any supplied reasons are in an array format
        if (!empty($_LW->widget['args']['reason']) && !is_array($_LW->widget['args']['reason'])) { 
                $_LW->widget['args']['reason']=array($_LW->widget['args']['reason']);
        };
        
        $reasons=array();
        
        // if reasons were supplied, validate and collect them
        if (!empty($_LW->widget['args']['reason'])) { 
                foreach($_LW->widget['args']['reason'] as $reason) {
                        if (!empty($reason)) {
                                $reasons[]=$reason;
                        };
                };
        };
        // if no reasons supplied
        if (empty($reasons)) { 
                // use the defaults
                $reasons=$_LW->REGISTERED_WIDGETS['feedback_form']['custom']['default_reasons']; 
        };
        
        // format reasons as markup for the template
        $reasons='<option>'.implode('</option><option>', $reasons).'</option>';
        
        // swap in template variables
        $template=str_replace(array( 
                '%%action%%',
                '%%title%%',
                '%%intro%%',
                '%%reasons%%'
               ),
               array(
                htmlspecialchars($_SERVER['REQUEST_URI']),
                $title,
                $intro,
                $reasons
               ), $template);
    };
    
    // require feedback form JS/CSS in the page
    $_LW->widget['metadata']['js'][]=$_LW->CONFIG['LIVE_URL'].'/resource/js/feedback_form%5Cfeedback_form.js'; 
    
    $_LW->widget['metadata']['css'][]=$_LW->CONFIG['LIVE_URL'].'/resource/css/feedback_form%5Cfeedback_form.css';
    
    // add the form to the widget output
    $_LW->widgetAdd($_LW->widget['xml']->xhtml($template)); 
    
    // create XHTML content
    $output=$_LW->widgetOutput(); 
    
    // return output in place of widget
    return $output; 
 }

}

?>



Step 3. Set up the widget's configuration file. This configuration file will make out feedback form widget available in LiveWhale's widget editor. 

In the /livewhale/client/modules/feedback_form directory, we will create a file named widget.feedback_form.config.php

Follow the strict naming conventions as you create this file by replacing the "feedback_form" portions with your widget name. 
 
<?php  
  $_LW->REGISTERED_CONFIGS['feedback_form']=array(
        // the title of this widget
        'title'=>'Feedback Form', 
         // the description of this widget
        'description'=>'The feedback form widget inserts a configurable feedback form into any page on your site.',
        // the possible args for this widget and their configuration for the widget editor
        'args'=>array( 
                'title'=>array('pre'=>'Display form with title', 'category'=>'Basic', 'defaultval'=>'Send us Feedback'),
                'intro'=>array('pre'=>'Display intro text', 'category'=>'Basic', 'defaultval'=>'Please fill out the form below and click submit.'),
                'reason'=>array('pre'=>'Optionally override reasons for feedback', 'category'=>'Basic', 'is_multiple'=>true)
        ),
        // there is no output format necessary for this widget
        'format'=>false 
  );
?>

Step 4. Create a template file by first adding an includes directory in /livewhale/client/modules/feedback_form.

In your new directory, /livewhale/client/modules/feedback_form/includes, create a new file, template.html.

The following variables: %%action%%, %%title%%, %%intro%%, %%reasons%%, will be overwritten with input from your widget arguments or will use the default content provided in your public.widget.feedback_form.php file in the registration code block.

<form id="feedback_form" action="%%action%%" method="post">
        <div class="feedback_msg"></div>
        <h3 class="feedback_title">%%title%%</h3>
        <div class="feedback_intro">%%intro%%</div>
        <div class="feedback_name">Name: <input type="text" name="name" placeholder="Your name"/></div>
        <div class="feedback_email_address">Email address: <input type="text" name="email_address" placeholder="Your email address"/></div>
        <div class="feedback_reason">Reason for feedback: <select name="reason">%%reasons%%</select></div>
        <div class="feedback_comments"><textarea name="comments" cols="40" rows="4"></textarea></div>
        <input type="hidden" name="is_feedback_form" value="1"/>
        <div class="feedback_submit"><input type="button" value="Submit"/></div>
</form>


Step 5. Include javascript for processing. In our form example, upon clicking on the submit button a javascript file will be executed validating our required fields and handling the submit action sending a success/error response.  

We created our script in the following directory structure: /livewhale/client/modules/feedback_form/scripts/feedback_form.js
 
(function($) {
  // on DOM ready
  $(function($) {
    var theForm=$('#feedback_form'); // find the feedback form
        if (theForm.length) {
                theForm.find('.feedback_submit').on('click', 'input', function() { 
                        // validate the form
                        if (theForm.find('.feedback_name input').val()=='') {
                                alert('You must enter your name to give feedback.');
                        }
                        else if (theForm.find('.feedback_email_address input').val()=='') {
                                alert('You must enter your email address to give feedback.');
                        }
                        else if (theForm.find('.feedback_reason input').val()=='') {
                                alert('You must enter a reason to give feedback.');
                        }
                        else if (theForm.find('.feedback_comments textarea').val()=='') {
                                alert('You must enter your comments to give feedback.');
                        }
                        else {
                          // submit the form and show the response
                          $.post(theForm.attr('action'), theForm.serialize(), function(response) {
                              if (response.error) {
                                theForm.find('.feedback_msg').html(response.error);
                              } 
                            else {
                                theForm.find('.feedback_msg').html(response.success);
                                    theForm.get(0).reset();
                            }
                         }, 'json');
                       };
                });
        };
  });
}(livewhale.jQuery));


Step 6. Now for the fun part, styling!  

In our example widget, we created some default css styling using the css classes and ids in our template.html file. 

We created a file in the following directory structure: /livewhale/client/modules/feedback_form/styles/feedback_form.css
#feedback_form {
        padding:10px;
        border:1px solid black;
        width:350px;
        background:white;
}

#feedback_form .feedback_title {
        text-align:center;
        color:#888888;
        font-family:Georgia,serif;
        font-size:1.8em;
        font-weight:400;
        margin-top:-5px;
}

#feedback_form .feedback_intro {
        color:#888;
        font-weight:normal;
        margin-top:-20px;
}

#feedback_form div {
        margin-top:10px;
        font-family:"Helvetica Neue", Arial, sans-serif;
}

#feedback_form input{
        margin:0 5px 0 0;
        font-family:"Helvetica Neue", Arial, sans-serif;
        font-size:0.9em;
        padding:3px;
}

#feedback_form .feedback_msg {
        font-weight:bold;
}

#feedback_form input[type="button"], input[type="submit"] {
        color:#333333;
        background-color:#eeeeee;
        border-color:#cccccc;
        background-image:linear-gradient(to bottom, #eee 0%, #ccc 100%);
        background-repeat:repeat-x;
        width:100%;
        padding:0.8rem 0;
        margin-top:10px;
        font-size:18px;
}

NOW, we have a widget that is available through our widget editor, we can override some of the form elements, we can process the form, and we have given it some default styling.

Here is what our default widget looks like......





Here is our widget under the editor as we override our form elements....



And, here is our widget syntax..

<widget type="feedback_form">
     <arg id="title">Rate this widget</arg>
     <arg id="intro">Please tell us what you think. Fill out the form below:</arg>
    <arg id="reason">Super!</arg>
    <arg id="reason">Average</arg>
    <arg id="reason">Poor</arg>
</widget>


Download the full example source code here
Attachments
eb8f96c071020d8b0923da726d6cab65@livewhale.desk-mail.com
https://cdn.desk.com/
false
desk
Loading
seconds ago
a minute ago
minutes ago
an hour ago
hours ago
a day ago
days ago
about
false
Invalid characters found
/customer/en/portal/articles/autocomplete?b_id=4256