Solved

How does this Javascript work?

Posted on 2016-08-04
5
61 Views
Last Modified: 2016-08-04
I've got some JS I'm attempting to deconstruct so I can add some functionality to it. First, however, I want to understand what I'm looking at. Here's what I've got:

First the JS itself:

define(['/assets/js/views/app2/custom_checkbox_and_radio.js','jquery'],function(){
    return function(){
      $('.at_filters label').click(function(){
        $(this).siblings('.checkbox').click();
      });
      $('input[name="filt"]').on('change',function(){
        if(this.value=='all'){
          if($(this).is(':checked')) $('input[name="filt"]').attr('checked', true);
          else $('input[name="filt"]').attr('checked', false);
        } else {
          $('input[name="filt"][value="all"]').attr('checked', false);
        }
        var show = [];
        var left = true;
        $('input[name="filt"]:checked').each(function(){
          show.push($(this).val());
        });
        var year = '';
        var month = '';
        $('.at_timeline_list li').each(function(){
          if($(this).hasClass('yearheader')){
            if(year && year.data('delete')) year.slideUp();
            else if(year) year.slideDown();
            year = $(this);
            year.data('delete', true);
          } else if($(this).hasClass('monthheader')){
            if(month && month.data('delete')) month.slideUp();
            else if(month) month.slideDown();
            month = $(this);
            month.data('delete', true);
          } else if($(this).hasClass('event')){
            if(show.indexOf($(this).data('type'))!=-1){
              $(this).removeClass('left').removeClass('right');
              $(this).addClass(left?'left':'right');
              left=!left;
              if($(this).css('display')!='list-item') $(this).slideDown();
              year.data('delete',false);
              month.data('delete',false);
            } else {
              if($(this).css('display')=='list-item') $(this).slideUp();
            }
          }
        });
        if(year && year.data('delete')) year.slideUp();
        else if(year) year.slideDown();
        if(month && month.data('delete')) month.slideUp();
        else if(month) month.slideDown();
      });

      //Account Search
      $('input.at_search').keypress(function(e){
        if(e.which == 13){
          $(this).siblings('.magnificon').click();
        }
      });
      $('.at_searchwrap .magnificon').click(function(){
        if(!$('.at_search').val()) return;
        pf.ajax({
          url:'/app/accounttimeline',
          data:{searchfor:$('.at_search').val()},
          type:'post',
          dataType:'json',
          success:function(res){
            if(res.success && res.body){
              if(res.loadAccount){
                pf.apps.loadApp({
                  appurl:'/app/accounttimeline',
                  postdata:{accountkey:res.loadAccount},
                  refresh:new Date()
                });
              } else pf.dialog(res.body, 'Search Results');
            } else {
              pf.dialog('There has been an issue processing your request. I apologize for the inconvenience, please try again.', 'Error');
            }
          }
        });
      });

      setupLabel();
    };
});

Open in new window


Here's a screenshot of the page:

screenshot
I want to break this down into several questions, just so I'm not wearing out my welcome.  What I want to do is define that which I understand and ask for confirmation on those things and then crescendo to that point where I've got a question. That said, here's the first "dilemma:"

define(['/assets/js/views/app2/custom_checkbox_and_radio.js','jquery'],function(){

I'm defining a series of variables located on the "customer_checkbox_and_radio.js" page (https://github.com/amdjs/amdjs-api/wiki/AMD). The next part says, "function." I'm thinking this is shorthand for "document.ready..." In other words, don't try to fire the function that's documented immediately following this syntax until the entire page is loaded.

The next part baffles me. I'm returning a function?

return function(){

The next body of code has this:

  $('.at_filters label').click(function(){
        $(this).siblings('.checkbox').click();
      });

What's happening here? I've got a class "at_filters label" which matches my code here:

<div class="at_searchwrap clearfix"><input class="at_search" placeholder="Search by first name, last name, or accountid."/><span class="magnificon"></span></div>
    <ul class="at_filters">
      <li>
        <span class="checkbox">
          <input type="checkbox" name="filt" value="all" checked/>
        </span><label>All</label>
      </li>
      <li>
        <span class="checkbox">
          <input type="checkbox" name="filt" value="transaction" checked/>
        </span><label>Transactions</label>
      </li>
      <li>
        <span class="checkbox">
          <input type="checkbox" name="filt" value="statement" checked/>
        </span><label>Statements</label>
      </li>
      <li>
        <span class="checkbox">
          <input type="checkbox" name="filt" value="note" checked/>
        </span><label>Notes</label>
      </li>
      <li>
        <span class="checkbox">
          <input type="checkbox" name="filt" value="comment" checked/>
        </span><label>Task Comments</label>
      </li>
	  <li>
        <span class="checkbox">
          <input type="checkbox" name="filt" value="personal_payments" checked/>
        </span><label>Personal Payments</label>
      </li>
    </ul>

Open in new window


Every one of these checkboxes is tied to this function, but what is that function doing?

What do you think?
0
Comment
Question by:brucegust
5 Comments
 
LVL 30

Assisted Solution

by:Alexandre Simões
Alexandre Simões earned 200 total points
ID: 41742723
1. define(['/assets/js/views/app2/custom_checkbox_and_radio.js','jquery'],function(){
This code is using an AMD as you already understood and this is not quite similar to document.ready because it has nothing to do with the page life-cycle.
Instead, what this makes sure is that the function at the end is not executed before the dependencies (the items in the array) have been loaded.

2. The next part baffles me. I'm returning a function?
Basically yes. Inside the AMD function you can do whatever you want, even returning a function.
This means that, other files that have this one as a dependency will receive a function that they will need execute.
If you remove that inner function, the whole code will execute right after all the dependencies have been loaded (putting it simple).

3. What's happening here? I've got a class "at_filters label" which matches my code
Well, this one either I'm getting it completely wrong or it's simply stupid.
What this javascript is trying to mimic is a default behavior of HTML that allows you to check or uncheck a checkbox by clicking an associated label (it works with other controls too).
Label HTML elements have a "for" attribute that serves exactly this purpose.
Simply get rid of this javascript, give a unique id to each checkbox and set that id as the value of the related label for attribute.
Something like:
  <li>
    <span class="checkbox">
          <input id="chkFilterComment" type="checkbox" name="filt" value="comment" checked/>
        </span>
    <label for="chkFilterComment">Task Comments</label>
  </li>

Open in new window

0
 
LVL 32

Accepted Solution

by:
it_saige earned 250 total points
ID: 41742741
There is alot going on here but it is relatively easy to understand once you break it down.

First, let's tackle the define([<stuff>],function(){<morestuff>});.  This is doing nothing more than defining a module.  More importantly, it is defining a module with dependencies.  The dependencies are declared in the array as defined by the first object ['/assets/js/views/app2/custom_checkbox_and_radio.js','jquery'].  In this case the dependencies for your module are the custom_checkbox_and_radio.js and jQuery; respectively.  The second object, the function(){<morestuff>} bit, is the module you are defining.

So what is your module doing?  Well that leads us into the second part, your module is returning a function that declares multiple functions and well as performing a sub/function call at the end (the sub and/or function is most likely declared in the custom_checkbox_and_radio.js dependency).  Here are the individual function calls within your modules returned function:
// using the jQuery(selector).action() syntax
// define a function that is called when the selector is clicked
$('.at_filters label').click(function () {
	$(this).siblings('.checkbox').click();
});

Open in new window

// using the jQuery(selector).action() syntax
// define a function that is called when the selector's onchange event is fired
$('input[name="filt"]').on('change', function () {
	if (this.value == 'all') {
		if ($(this).is(':checked')) $('input[name="filt"]').attr('checked', true);
		else $('input[name="filt"]').attr('checked', false);
	} else {
		$('input[name="filt"][value="all"]').attr('checked', false);
	}
	var show = [];
	var left = true;
	$('input[name="filt"]:checked').each(function () {
		show.push($(this).val());
	});
	var year = '';
	var month = '';
	$('.at_timeline_list li').each(function () {
		if ($(this).hasClass('yearheader')) {
			if (year && year.data('delete')) year.slideUp();
			else if (year) year.slideDown();
			year = $(this);
			year.data('delete', true);
		} else if ($(this).hasClass('monthheader')) {
			if (month && month.data('delete')) month.slideUp();
			else if (month) month.slideDown();
			month = $(this);
			month.data('delete', true);
		} else if ($(this).hasClass('event')) {
			if (show.indexOf($(this).data('type')) != -1) {
				$(this).removeClass('left').removeClass('right');
				$(this).addClass(left ? 'left' : 'right');
				left = !left;
				if ($(this).css('display') != 'list-item') $(this).slideDown();
				year.data('delete', false);
				month.data('delete', false);
			} else {
				if ($(this).css('display') == 'list-item') $(this).slideUp();
			}
		}
	});
	if (year && year.data('delete')) year.slideUp();
	else if (year) year.slideDown();
	if (month && month.data('delete')) month.slideUp();
	else if (month) month.slideDown();
});

Open in new window

// using the jQuery(selector).action() syntax
// define a function that is called when the selector's keypressed event is fired
$('input.at_search').keypress(function (e) {
	if (e.which == 13) {
		$(this).siblings('.magnificon').click();
	}
});

Open in new window

// using the jQuery(selector).action() syntax
// define a function that is called when the selector is clicked
$('.at_searchwrap .magnificon').click(function () {
	if (!$('.at_search').val()) return;
	pf.ajax({
		url: '/app/accounttimeline',
		data: { searchfor: $('.at_search').val() },
		type: 'post',
		dataType: 'json',
		success: function (res) {
			if (res.success && res.body) {
				if (res.loadAccount) {
					pf.apps.loadApp({
						appurl: '/app/accounttimeline',
						postdata: { accountkey: res.loadAccount },
						refresh: new Date()
					});
				} else pf.dialog(res.body, 'Search Results');
			} else {
				pf.dialog('There has been an issue processing your request. I apologize for the inconvenience, please try again.', 'Error');
			}
		}
	});
});

Open in new window

// Call the setupLabel sub/function most likely defined in - 
// /assets/js/views/app2/custom_checkbox_and_radio.js
setupLabel();

Open in new window


-saige-
0
 
LVL 51

Assisted Solution

by:Julian Hansen
Julian Hansen earned 50 total points
ID: 41742753
To add to Alex's post

Agree about the stupid code for item 3 - just use a for.

Based on your earlier question, your code is using the RequireJS library

You can read more about it here http://requirejs.org/docs/api.html#define

It might help to shed some more light on your first question.
0
 

Author Comment

by:brucegust
ID: 41743020
Gentlemen! Thanks so much for your time! Let me explain back to you what you have above and then feel free to weigh in on the second part of the question (https://www.experts-exchange.com/questions/28961568/How-does-this-Javascript-work-Part-II.html).

Here's the custom_checkbox_radio...js:

// Custom checkbox and radios
function setupLabel() {
    // Checkbox
    var checkBox = ".checkbox";
    var checkBoxInput = checkBox + " input[type='checkbox']";
    var checkBoxChecked = "checked";
    var checkBoxDisabled = "disabled";

    // Radio
    var radio = ".radio";
    var radioInput = radio + " input[type='radio']";
    var radioOn = "checked";
    var radioDisabled = "disabled";

    // Checkboxes
    if ($(checkBoxInput).length) {
        $(checkBox).each(function(){
            $(this).removeClass(checkBoxChecked);
        });
        $(checkBoxInput + ":checked").each(function(){
            $(this).parent(checkBox).addClass(checkBoxChecked);
        });
        $(checkBoxInput + ":disabled").each(function(){
            $(this).parent(checkBox).addClass(checkBoxDisabled);
        });
    }

    // Radios
    if ($(radioInput).length) {
        $(radio).each(function(){
            $(this).removeClass(radioOn);
        });
        $(radioInput + ":checked").each(function(){
            $(this).parent(radio).addClass(radioOn);
        });
        $(radioInput + ":disabled").each(function(){
            $(this).parent(radio).addClass(radioDisabled);
        });
    }
}

$(document).ready(function(){
    $("html").addClass("has-js");
    //console.log('docready');
    // First let's prepend icons (needed for effects)
    $(".checkbox, .radio").filter(function(){
        return $(this).data('prepended')?false:true;
    }).prepend("<span class='icon'></span><span class='icon-to-fade'></span>").data('prepended',true);

    $(document).off('click.customchecksnsech').on('click.customchecksnsech', ".checkbox, .radio", function(e){
        $(this).children('input[type="checkbox"]').attr('checked',!$(this).children('input').attr('checked')).change();
        $(this).children('input[type="radio"]').attr('checked',true).change();
        //$(this).children('input[type="radio"]').change();
        //console.log($(this));
        setupLabel();
    });
    setupLabel();
});

function refreshInputs(){
    $(".checkbox, .radio").filter(function(){
        return $(this).data('prepended')?false:true;
    }).prepend("<span class='icon'></span><span class='icon-to-fade'></span>").data('prepended',true);
    setupLabel();
}

Open in new window


I'm establishing the digital presence of those entities and then "coupling" those entities with the functionality that's documented after the "return function."

At the beginning of the "return function," you've got this:

      $('.at_filters label').click(function(){
        $(this).siblings('.checkbox').click();
      });

If I'm hearing the tone of your voice correctly, it's almost pointless. What you're doing is coupling the checkboxes with the labels that go along with the "at_filters" class. And while it may work, it's not good programming.

Correct?

Let me know and feel free to take a look at Part II (https://www.experts-exchange.com/questions/28961568/How-does-this-Javascript-work-Part-II.html)!
0
 
LVL 30

Expert Comment

by:Alexandre Simões
ID: 41743048
If I'm hearing the tone of your voice correctly, it's almost pointless.
No, it's stupid :)
It denotes a big lack of HTML knowledge. Just delete it and use the "for" attribute on the labels.
Sorry for my language, I'm usually not this aggressive, but there are certain things that really drive me mad, and this kind of code is one of them :)
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

This article will give core knowledge of JavaScript and will head in to your first JavaScript program. I am Durvesh Naik and I am here to deal with this series of JavaScript. I will teach you JavaScript in part wise , as its quite boring to read big…
International Data Corporation (IDC) prognosticates that before the current the year gets over disbursing on IT framework products to be sent in cloud environs will be $37.1B.
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
The viewer will learn the basics of jQuery including how to code hide show and toggles. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery…

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now