#StackBounty: #javascript #jquery #html #datatables #codeigniter-3 How to filter data-tables using two or more dependent drop-down list?

Bounty: 50

I’m trying to apply filters to my data-table with drop-down list box which are dependent. But when i’m trying to select a value from drop-down, data-table takes value from only one drop-down.

Here is my code:

Script:


  $(document).ready(function(){
    var dataTable = $('#exampleProp').DataTable({
      "processing": true,
      "serverSide": true,
      "dom": 'lfrtip',
      "ajax": {
        "url": "",
        "dataType": "json",
        "type": "POST"
      },
      "lengthMenu": [[50, 100, 200, -1], [50, 100, 200, "All"]],
      // "ordering": false,
    });

    $('#areaId').on('change', function(){
      if (this.value == 1) {
        dataTable.search("Midlands & East of England").draw();
      } else {
        dataTable.search("North East, Yorkshire & Humberside").draw();
      }
    });
    $('#cluster_id').on('change', function(){
       dataTable.search(this.value).draw();   
    });
    $('#prop_type').on('change', function(){
       dataTable.search(this.value).draw();   
    });
    $('#prop_status').on('change', function(){
       dataTable.search(this.value).draw();   
    });

  });

In this, Cluster is dependent on Area, but if I select Area, it filters using area only, and not by cluster.

Here is the code to pick a cluster list from database:

$('#areaId').change(function(){
         var form_date =
         $.ajax({
          url: "<?= base_url('Property/clusterlistAddPropertyUse'); ?>",
          data: {areaId:$(this).val()},
          method:'POST',
          dataType: 'html',
          success:function(data){
              // $('#cluster_id option:selected').each(function(){
              // $(this).prop('selected', false);
              // });
              $('#cluster_id').html(data); 
              $('.propcluster').multiselect('rebuild');                 
             }
          }); 
    });

Here is my view code:

<?php if($this->session->flashdata('success_msg')){ ?>
  
session->flashdata('success_msg'); ?>
<?php } ?> <?php if($this->session->flashdata('error_msg')){ ?>
session->flashdata('error_msg'); ?>
<?php } ?>
Property List
All area_id; ?>">area_name; ?>
All cluster_name; ?>
All property_type_name;?>
All stage_name; ?>
</div>
<!-- --> <!-- -->
Code Date Type ASYS Address1AreaCity Status Landlord Rooms Edit Action
Code Date Type ASYS No Address1AreaCity Status Landlord Rooms Edit Action
</div>

I want to filter data with both area and cluter and then type and stage also.

Edit:
**

For more details, I’m adding Controller and model code here:

**

Model

public function prop_query()
{
    # code...
    $this->db->select('property_id, property_code, property_added_date, property_updated_date, property_type, tbl_property_type.property_type_name as type, property_ASYS_no, property_address_1, property_area, tbl_area.area_name as area, property_cluster, tbl_cluster.cluster_name as cluster, property_status, tbl_property_stage.stage_name as stage, property_landlord_id, concat(tbl_landlord.landlord_first_name, tbl_landlord.landlord_middle_name, tbl_landlord.landlord_last_name) as landlord, property_postcode, count(tbl_rooms.room_property_id) as rooms,');
    $this->db->from($this->property);

    $this->db->join('tbl_property_type', 'tbl_property.property_type = tbl_property_type.property_type_id', 'left');
    $this->db->join('tbl_area', 'tbl_property.property_area = tbl_area.area_id', 'left');
    $this->db->join('tbl_cluster', 'tbl_property.property_cluster = tbl_cluster.cluster_id', 'left');
    $this->db->join('tbl_property_stage', 'tbl_property.property_status = tbl_property_stage.stage_id', 'left');
    $this->db->join('tbl_landlord', 'tbl_property.property_landlord_id = tbl_landlord.landlord_id', 'left');
    $this->db->join('tbl_rooms', 'tbl_property.property_id = tbl_rooms.room_property_id', 'left');

    // $whereArray = array('tbl_property.property_type' => $propertyType, 'tbl_property.property_area' => $area, 'tbl_property.property_status' => $stageId, 'tbl_property.property_cluster' => '$clusterString');

    // $this->db->where('tbl_property.property_type', $propertyType);
    // $this->db->where('tbl_property.property_area', $area);
    // $this->db->where('tbl_property.property_status', $stageId);
    // $this->db->where('tbl_property.property_cluster', $clusterString);

    $this->db->group_by('tbl_property.property_id');
    // $this->db->order_by("tbl_property.property_updated_date", "DESC");

    if (isset($_POST["search"]["value"])) {
        # code...
        $this->db->like("property_id", $_POST["search"]["value"]);
        $this->db->or_like("property_code", $_POST["search"]["value"]);
        $this->db->or_like("property_added_date", $_POST["search"]["value"]);
        $this->db->or_like("tbl_property_type.property_type_name", $_POST["search"]["value"]);
        $this->db->or_like("property_ASYS_no", $_POST["search"]["value"]);
        $this->db->or_like("property_address_1", $_POST["search"]["value"]);
        $this->db->or_like("tbl_area.area_name", $_POST["search"]["value"]);
        $this->db->or_like("tbl_cluster.cluster_name", $_POST["search"]["value"]);
        $this->db->or_like("tbl_property_stage.stage_name", $_POST["search"]["value"]);
        $this->db->or_like("concat(tbl_landlord.landlord_first_name, tbl_landlord.landlord_middle_name, tbl_landlord.landlord_last_name)", $_POST["search"]["value"]);
        $this->db->or_like("property_postcode", $_POST["search"]["value"]);
    }

    if (isset($_POST["order"])) {
        # code...
        // $this->db->order_by("tbl_property.property_updated_date", "DESC");
        $this->db->order_by($this->order_column[$_POST['order']['0']['column']], $_POST['order']['0']['dir']);
    } else {
        # code...
        $this->db->order_by("tbl_property.property_updated_date", "DESC");
        // $this->db->order_by($this->order_column[$_POST['order']['0']['column']], $_POST['order']['0']['dir']);
    }
}

public function prop_datatables()
{
    # code...
    $this->prop_query();

    if ($_POST["length"] != -1) {
        # code...
        $this->db->limit($_POST["length"], $_POST["start"]);
    }

    $query = $this->db->get();

    return $query->result();
}

public function prop_filtered_data()
{
    # code...
    $this->prop_query();
    $query = $this->db->get();

    return $query->num_rows();
}

public function prop_all_data()
{
    # code...
    $this->db->select("*");
    $this->db->from($this->property);

    return $this->db->count_all_results();
}

Controller:

public function fetchProp()
{
    # code...
    $user = $this->ion_auth->user()->row();
    $data['username'] = $user->username;

    $data['user_id'] = $user->id;
    $user_id = $user->id;
    $data['groupId'] = $this->l->groupId($user_id);
    $data['group'] = $data['groupId']['0']->group_id;

    $fetch_prop = $this->pm->prop_datatables();

    $data = array();

    foreach ($fetch_prop as $row) {
        # code...
        $sub_array = array();
        $sub_array[] = $row->property_code;
        $sub_array[] = $row->property_added_date;
        $sub_array[] = $row->type;
        $sub_array[] = $row->property_ASYS_no;
        $sub_array[] = $row->property_address_1;
        // $sub_array[] = $row->area;
        $sub_array[] = $row->cluster;
        $sub_array[] = $row->stage;
        $sub_array[] = $row->landlord;
        $sub_array[] = $row->rooms;

            }
        }


        // $sub_array[] = '<a style="text-decoration: none;" href="'.base_url('Property/propertyDetails/'.$row->property_id).'" class="btn-warning btn-xs">View</a>&nbsp;
        // <a style="text-decoration: none;" href="'.base_url('Property/viewRoom/'.$row->property_id).'" class="btn-success btn-xs">Rooms</a>';


        $data[] = $sub_array;
    }

    $output = array(
        "draw" => intval($_POST["draw"]),
        "recordsTotal" => $this->pm->prop_all_data(),
        "recordsFiltered" => $this->pm->prop_filtered_data(),
        "data" => $data
    );

    echo json_encode($output);
}

I’m gone through this link Data-Tables, But it gives result from columns from table only, I’m not showing area column in the table.

Edit_2:

While googled, I got this link, Search API (regular expressions), Data table specific column filter with multi select drop down
, Individual column searching (select inputs)
, I’m trying to achieve result like this, But with Drop-down box.

Any kind of help is welcome. Thanks in advance.


Get this bounty!!!

#StackBounty: #javascript #jquery #reactjs #webpack #ecmascript-6 webpack use amd Define

Bounty: 50

Im trying to convert my company project, from JSPM and systemJS to webpack.
So i started a new project from scratch and instaled basic configuration.

I need to include in the project a old package that was build by former collegues. The package was develop in Jquery and use the AMD define method.

So i search and finded imports-loader.

In my webpack configuration i have:

{
      test: path.resolve(__dirname, 'vendor/module/module.js'),
      loader: "imports-loader?this=>window&define=>false"
},

And in my code i have the follow:

import Module from 'module';
new Module.WindowManager(arg1, arg2);

when i run the webpack, i got this error:

Uncaught Error: module/wm/window missing module/core/emitter

In the module that im trying to use the module/core/emitter are use here:

define('module/wm/window', 
    ['module/core/emitter'], function (Emitter) { ... });


Get this bounty!!!

#StackBounty: #javascript #jquery #html #dom #jquery-ui Create multiple parametherized JQueryUI dialog boxes

Bounty: 50

In my application, I am using a lot of jQueryUI dialog boxes.
In order to reduce the length of code, and because I am using often the very same parameterization, I was wondering about a way to efficiently and easily create multiple dialogs.

I ended up with that: I’ve created 2 functions (dialog_OkCancel and dialog_Input_OkCancel) that call the same “main” dialog_handler.
That way I avoid calling the big main function and use only the little and easier ones.

These functions are pretty simple so I don’t know what else to add. 🙂

Here is a working snippet of my code to illustrate that:

// jQuery UI dialog custom management
function dialog_Handler({
  title,
  message,
  buttons,
  input
}) {
  $("<p>" + message + "</p>").dialog({ // Could use “var dialog = ”
    //autoOpen: false,                  // false would prevents regular opening
    show: "drop",
    open: function(event, ui) {
      // Overlay parameterization
      $("div.ui-widget-overlay").css({
        "background": "#000",
        "opacity": "0.4"
      });
      $(".ui-widget-overlay").hide().fadeIn();
      // Adds some more configuration if input needed
      if (input) {
        // Adds input field right under the message
        $(this).append('<br /><br /><input id="dialog_Input" style="width: 350px; padding: 4px;" type="text" value="' + input + '"><br />');
        // Binds “Enter” to press first button (usually “Ok”)
        $(this).keydown(function(event) {
          if (event.keyCode == $.ui.keyCode.ENTER) {
            $(this).parent().find("button:eq(1)").trigger("click");
            return false;
          }
        });
      }
    },
    title: title,
    buttons: buttons,
    modal: true,
    resizable: false,
    height: "auto",
    width: 400,
    hide: {
      effect: "drop",
      duration: "fast"
    },
    closeOnEscape: true,
    // Overlay fadeout
    beforeClose: function(event, ui) {
      // Wait for the overlay to be faded out to try closing again
      if ($('.ui-widget-overlay').is(":visible")) {
        $('.ui-widget-overlay').fadeOut("fast", function() {
          $('.ui-widget-overlay').hide();
          $('.ui-icon-closethick').trigger('click');
        });
        return false;
      }
    },
    close: function() {
      $(this).dialog("destroy");
    }
  });
  return;
}

function dialog_OkCancel({
  title,
  message,
  funk_Ok
}) {
  var buttons = {
    "Ok": function() {
      funk_Ok();
      $(this).dialog("close");
    },
    "Cancel": function() {
      $(this).dialog("close");
    }
  }
  dialog_Handler({
    title,
    message,
    buttons
  });
  return;
}

function dialog_Input_OkCancel({
  title,
  message,
  input,
  funk_Ok
}) {
  var buttons = {
    "Ok": function() {
      funk_Ok();
      $(this).dialog("close");
    },
    "Cancel": function() {
      $(this).dialog("close");
    }
  }
  dialog_Handler({
    title,
    message,
    buttons,
    input
  });
  return;
}

function dialog_YesNoCancel({
  title,
  message,
  funk_Yes,
  funk_No
}) {
  var buttons = {
    "Yes": function() {
      funk_Yes();
      $(this).dialog("close");
    },
    "No": function() {
      funk_No();
      $(this).dialog("close");
    },
    "Cancel": function() {
      $(this).dialog("close");
    }
  }
  dialog_Handler({
    title,
    message,
    buttons
  });
  return;
}
.dialog {
  display: block;
  margin: 8px;
  text-align: center;
  width: 120px;
}
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js
https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" />

<html>

<body>

  <button class="dialog" onclick='dialog_OkCancel({
      title: "Title",
      message: "I do not have any idea for the message.",
      funk_Ok: function(){ console.log("Sorry. :("); }
    });'>Dialog<br>Ok/Cancel</button>
  <button class="dialog" onclick='dialog_Input_OkCancel({
      title: "Title",
      message: "I do not have any idea for the message.",
      input: "Type something…", 
      funk_Ok: function(){ console.log("Give me more words ! :)"); }
    });'>Dialog<br>Input</button>
  <button class="dialog" onclick='dialog_YesNoCancel({
      title: "Just talking…",
      message: "Are you fine?",
      funk_Yes: function(){ console.log("You said “Yes”! :)"); },
      funk_No: function(){ console.log("You said “No”! :("); }
    });'>Dialog<br>Yes/No/Cancel</button>
</body>

</html>

This snippet is one piece of code out of many.
I would like that piece of code to be improved… So I could improve all others.
How would you do it?
What would be your method to improve the management of multiple functions?


Get this bounty!!!

#StackBounty: #javascript #jquery Create multiple parametherized JQueryUI dialog boxes

Bounty: 50

In my application, I am using a lot of jQueryUI dialog boxes.
In order to reduce the length of code, and because I am using often the very same parameterization, I was wondering about a way to efficiently and easily create multiple dialogs.

I ended up with that: I’ve created 2 functions (dialog_OkCancel and dialog_Input_OkCancel) that call the same “main” dialog_handler.
That way I avoid calling the big main function and use only the little and easier ones.

These functions are pretty simple so I don’t know what else to add. 🙂

Here is a working snippet of my code to illustrate that:

// jQuery UI dialog custom management
function dialog_Handler({
  title,
  message,
  buttons,
  input
}) {
  $("<p>" + message + "</p>").dialog({ // Could use “var dialog = ”
    //autoOpen: false,                  // false would prevents regular opening
    show: "drop",
    open: function(event, ui) {
      // Overlay parameterization
      $("div.ui-widget-overlay").css({
        "background": "#000",
        "opacity": "0.4"
      });
      $(".ui-widget-overlay").hide().fadeIn();
      // Adds some more configuration if input needed
      if (input) {
        // Adds input field right under the message
        $(this).append('<br /><br /><input id="dialog_Input" style="width: 350px; padding: 4px;" type="text" value="' + input + '"><br />');
        // Binds “Enter” to press first button (usually “Ok”)
        $(this).keydown(function(event) {
          if (event.keyCode == $.ui.keyCode.ENTER) {
            $(this).parent().find("button:eq(1)").trigger("click");
            return false;
          }
        });
      }
    },
    title: title,
    buttons: buttons,
    modal: true,
    resizable: false,
    height: "auto",
    width: 400,
    hide: {
      effect: "drop",
      duration: "fast"
    },
    closeOnEscape: true,
    // Overlay fadeout
    beforeClose: function(event, ui) {
      // Wait for the overlay to be faded out to try closing again
      if ($('.ui-widget-overlay').is(":visible")) {
        $('.ui-widget-overlay').fadeOut("fast", function() {
          $('.ui-widget-overlay').hide();
          $('.ui-icon-closethick').trigger('click');
        });
        return false;
      }
    },
    close: function() {
      $(this).dialog("destroy");
    }
  });
  return;
}

function dialog_OkCancel({
  title,
  message,
  funk_Ok
}) {
  var buttons = {
    "Ok": function() {
      funk_Ok();
      $(this).dialog("close");
    },
    "Cancel": function() {
      $(this).dialog("close");
    }
  }
  dialog_Handler({
    title,
    message,
    buttons
  });
  return;
}

function dialog_Input_OkCancel({
  title,
  message,
  input,
  funk_Ok
}) {
  var buttons = {
    "Ok": function() {
      funk_Ok();
      $(this).dialog("close");
    },
    "Cancel": function() {
      $(this).dialog("close");
    }
  }
  dialog_Handler({
    title,
    message,
    buttons,
    input
  });
  return;
}
https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js
https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" />

<html>

<body>

  <button onclick='dialog_OkCancel({
      title: "Title",
      message: "I do not have any idea for the message.",
      funk_Ok: function(){ console.log("Sorry. :("); }
    });'>Dialog Ok/Cancel</button>
  <button onclick='dialog_Input_OkCancel({
      title: "Title",
      message: "I do not have any idea for the message.",
      input: "Type something…", 
      funk_Ok: function(){ console.log("Give me more words ! :)"); }
    });'>Dialog Input</button>
</body>

</html>

This snippet is one piece of code out of many.
I would like that piece of code to be improved… So I could improve all others.
How you, guys, would do it?
What would be your method to improve that multiple functions management?


Get this bounty!!!

#StackBounty: #javascript #jquery #html #jquery-plugins #footable Reload data from sql footable

Bounty: 50

i am using a footable and i need to reload it on a button click but without appending html to the table, i need to reload it from sql as it is filled the first time, is that possible

i have tried to realod the div $("#BusList").load(location.href + " #BusList"); the data is loaded but the design is totally messed up

  
Name Company Bus Type Bus Model Bus Color Driver Status Bus Status
"> ">
    </td> </tr> </tfoot> </table> </div>


    Get this bounty!!!

    #StackBounty: #javascript #jquery #json #ecmascript-6 #quiz Quiz app from JSON file (ES6, JQuery)

    Bounty: 50

    My code fetches quiz data from a JSON file, displays the questions sequentially and records the user’s answers. It keeps track of the user’s score and at the end display the user’s result based on a second JSON file.

    const QUIZ_API = 'quiz.json';
    const RESULT_API = 'result.json';
    const QUIZ_ID = 12;  // Used to identify the quiz in the JSON file.
    
    let jsonQuizData;
    let questionNo = 0; // Current question number
    let answerSubmitted = false; // Is set to true once the user submits an answer to the current question and still hasn't proceeded to the next one.
    let points = 0; // User's current score
    let maxPoints = 0; // Max possible score for quiz
    
    /*
    * When the document is ready, adds a key listener to enable playing the quiz using the keyboard only, and loads quiz data.
     */
    $(document).ready(() => {
        // Allow submitting answer with Enter key
        document.addEventListener('keyup', (event) => {
            if (event.keyCode === 13) // 13 is the Enter key
                $('#next-btn').click();
        });
    
        $.getJSON( QUIZ_API, { quiz_id: QUIZ_ID})
            .done((resp) => {
                jsonQuizData = resp;
                $('h1').text(resp.title);
                $('h2').html('&ldquo;' + resp.description + '&rdquo;');
                updateQuestionDisplay(resp.questions[0]);
            })
            .fail(() => {
                alert('The quiz is not available at the moment! Please try again later.');
            });
    });
    
    /*
    * Displays the current question and its possible answers
    * @param {Object} qObject - Object representing the current question
    */
    function updateQuestionDisplay(qObject) {
        /* Question image */
        const imageAlt = `Question ${questionNo + 1} image`;
        $('#question').find('img').attr({
            src: qObject.img,
            alt: imageAlt
        });
    
        /* Question header (Question number, question title, question points) */
        let maxStr = ''; // Questions with multiple answers will have the word 'max' after the number of points, in order to show that the user may receive fewer points for a partially correct answer.
        if (qObject.question_type === 'mutiplechoice-multiple')
            maxStr = ' max';
        let ptsStr = qObject.points === 1? ' pt': ' pts';
        $('#qTitle').html(qObject.q_id + '. ' + qObject.title + ' <strong>[' + qObject.points + ptsStr + maxStr + ']</strong>');
    
        /* Question type */
        let inputType;
        switch(qObject.question_type) {
            case 'mutiplechoice-multiple':
                inputType = 'checkbox';
                break;
            default:
                inputType = 'radio';
        }
    
        /* Answers */
        const inputsContainer = $('#inputs');
        inputsContainer.css('text-align', 'left');
    
        if (qObject.question_type === 'truefalse') {
            inputsContainer.append(`
            
    `); inputsContainer.append(`
    `); } else qObject.possible_answers.forEach((item) => { inputsContainer.append(`
    `); }); } /* * Performs appropriate task on clicking button based on answerSubmitted */ function nextButtonClicked() { if (answerSubmitted) nextQuestion(); else submitAnswer(); } /* * Validates and submits the user's answer, changes document and styles accordingly. */ function submitAnswer() { const inputs = $('input'); let ans = []; // ans is an array to accomodate the case of multiple answer questions. inputs.each((i, obj) => { if (obj.checked) ans.push(obj.id); // obj.id is always a string. }); if (!ans.length) alert('No answer selected!'); else { // If an answer was selected answerSubmitted = true; checkAnswer(ans); const nextBtn = $('#next-btn'); inputs.attr('disabled', 'disabled'); nextBtn.attr('disabled', 'disabled'); $('#inputs').css('text-align', 'center'); let newButtonText = jsonQuizData.questions[questionNo + 1]? 'Next question': 'See results!'; $(this).delay(500).queue(() => { nextBtn.text(newButtonText); nextBtn.removeAttr('disabled'); $(this).dequeue(); }); } } /* * Performs 2 tasks: * 1. Add css to indicate the correct answer and highlight the user's chosen answer. * 2. Check answer and update points. * @param {string[]} answer - User's submitted answer */ function checkAnswer(answer) { const correctAnswer = jsonQuizData.questions[questionNo].correct_answer; let pointsToAward = jsonQuizData.questions[questionNo].points; maxPoints += pointsToAward; // Update maxPoints for the current question. /* 1. Add css to indicate the correct answer and highlight the user's answer. */ if (jsonQuizData.questions[questionNo].question_type === 'truefalse') { // For true-false questions it is straightforward $('label[for="' + correctAnswer.toString() + '"]').addClass('correct'); $('label[for="' + (!(correctAnswer)).toString() + '"]').addClass('incorrect'); $('label[for="' + answer.toString() + '"]').parent().addClass('selected'); } else { // For questions which are not of true-false type jsonQuizData.questions[questionNo].possible_answers.forEach((obj, i) => { if (answer.includes(obj.a_id.toString())) $('label[for="' + obj.a_id.toString() + '"]').parent().addClass('selected'); if (typeof correctAnswer === 'object' && correctAnswer != null && correctAnswer.includes(jsonQuizData.questions[questionNo].possible_answers[i].a_id) || correctAnswer === obj.a_id) $('label[for="' + obj.a_id.toString() + '"]').addClass('correct'); else $('label[for="' + obj.a_id.toString() + '"]').addClass('incorrect'); }); } /* 2. Check answer and update points. */ if (typeof jsonQuizData.questions[questionNo].correct_answer === 'object' && jsonQuizData.questions[questionNo].correct_answer != null) { // The if statement checks if it is a question with multiple answers. This is because 'object' is the type of arrays, and of null. Since correct_answer might be null, we check if it's not null as well. const noOfItems = jsonQuizData.questions[questionNo].possible_answers.length; let resultBool = new Array(noOfItems).fill(false); // For each option, resultBool[i] is false if the user's answer is wrong, else true. // Setting resultBool jsonQuizData.questions[questionNo].possible_answers.forEach((obj, i) => { if (correctAnswer.includes(obj.a_id) && answer.includes(obj.a_id.toString()) || !correctAnswer.includes(obj.a_id) && !answer.includes(obj.a_id.toString())) resultBool[i] = true; }); resultBool.forEach((obj) => { if (!obj) pointsToAward = pointsToAward - !!pointsToAward; // Decrements pointsToAward by 1 if it's greater than 0. }); points += pointsToAward; } else { // Questions with a single answer if (answer[0] === correctAnswer.toString()) points += pointsToAward; } } /* * If a subsequent question exists, increments questionNo and displays the next question * with the help of updateQuestionDisplay(). Else, calls displayResults. */ function nextQuestion() { if (jsonQuizData.questions[questionNo + 1]) { // If there is a next question // Remove current options $('.option').each((i, obj) => { obj.remove(); }); // Replace image with placeholder image so users with slow internet connections do not see the previous level's image while the new level's image is still loading. $('.img-container-small').find('img').attr('src', 'img/placeholder-image.png'); // Set button text $('#next-btn').text('Submit'); // Set answerSubmitted to false answerSubmitted = false; // Increment question number and display next question updateQuestionDisplay(jsonQuizData.questions[++questionNo]); } else displayResults(); } /* * Calculates the user's score as a percentage, loads the result data, finds the user's * result group, displays the user's result. */ function displayResults() { const pointsPercent = Math.round(points / maxPoints * 100); let resultGroupIndex = 0; let jsonResultsData; $.getJSON( RESULT_API, { quiz_id: QUIZ_ID}) .done((resp) => { jsonResultsData = resp; jsonResultsData.results.forEach((obj, i) => { if (pointsPercent >= obj.minpoints) resultGroupIndex = i; }); $('main').html(` <section> <h3>Quiz completed! Points earned: <strong>${points}/${maxPoints} (${pointsPercent}%)</strong></h3> <p class="huge-font m-y-sm">${jsonResultsData.results[resultGroupIndex].title}</p>
    Result image
    <p class="p-b-md">${jsonResultsData.results[resultGroupIndex].message}</p> </section> `); }) .fail(() => { alert('Your result is not available at the moment! Please try again later.'); }); }

    The reason I use global variables and all my functions have global scope is because in my HTML file I have this:

    <button id="next-btn" onclick="nextButtonClicked()">Submit</button>
    

    Since my HTML button references nextButtonClicked(), the function has to have global scope. Since this function eventually ends up calling all the other functions and also needs to use the global variables, I have also given them global scope.

    However, I am not sure if this is the best way to go about solving this problem.

    Also, I’m wondering if it would be a good idea to use namespaces and how.

    Moreover, the only ES6 features I’m using are arrow functions,let and const. Are there other ES6 features that I can incorporate?

    If you have any other feedback not related to the issues I mentioned I’d love to receive it too.


    Get this bounty!!!

    #StackBounty: #javascript #jquery #google-maps #google-apps-script #async.js Bottlenecks in asynchronous JavaScript code for Google Map

    Bounty: 50

    I’m working on a pothole map web app in Google Apps Script. The map gets its data from a Google spreadsheet (from manual surveying), which is then transformed via hits to the Geolocation and Google Maps Roads APIs. There are 101 markers on the map (one marker per row of data, which represents either a pothole or a cluster of potholes). This map, for some odd reasons, takes about 20 seconds to load initially. Unacceptable!

    This app makes use of the following APIs:

    • jQuery
    • Google Maps Roads
    • Google Geolocation
    • async.js
    • Mustache.js

    I profiled my code , and from what it seems, most of the CPU time is from methods that don’t appear to be business ones. I analyzed the code profile two ways:

    Self time

    There were at least three heavy function calls in this respect, although nothing that seems to be too bad.
    enter image description here

    Total time

    There was no business logic right at the top of this list, but plenty right below it. I present thus:
    enter image description here

    I then identify the lines of code where these bottlenecks appear:

    addPotholeMarker()

    /* Adds marker to map.
     * Parameters : 
     *  • potholeData  : a PotholeData (or PotholeDataFromCoords) object
     *  • snappedToRoad: boolean
     *  • callback     : the function to call next (optional)
     * Returns : 
     *  • the marker that was added to the map, or null if arguments invalid, or callback() if it was provided
     */
    function addPotholeMarker(potholeData, snappedToRoad, callback) {
      // make sure that callback is either falsy or a function
      if ((callback) && (typeof callback !== 'function')) throw new TypeError('callback specified but not a function. Thrown from addPotholeMarker()'); 
      // make sure potholeState is either falsy or contains iconURL string
      if ((!potholeData.potholeState) || ((potholeData.potholeState) && (potholeData.potholeState.iconURL === undefined))) throw new Error('invalid potholeData');
      // let's make sure to snap this to road if it isn't already...  
      var coords = new GPSCoordinates(potholeData.lat, potholeData.lng);
      if (!snappedToRoad) 
      { 
        var potholeMarker = 'a garbage return value';
        getRoadCoordinates(coords).done(function(response) {
            var coords = response.snappedPoints[0].location;
            potholeData.lat = coords.latitude;
            potholeData.lng = coords.longitude;
            potholeData.isSnappedToRoad(true);
            return (potholeMarker = addPotholeMarker(potholeData, true, callback));
       /*     potholeMarker = addPotholeMarker(potholeData, true);
            return potholeMarker;*/
        });
        if (callback) return callback(null);
        return; 
        //return potholeMarker;
      }
      var marker = new google.maps.Marker({
        position: coords,
        title: coords.toString(),
        map: map,
        opacity: 0.5,
        icon: ((potholeData.potholeState.iconURL !== undefined) ? potholeData.potholeState.iconURL : PURPLE_MARKER)
      });
    
      // make marker have effect when mouseout,mouseover
      marker.addListener('mouseover', function(mouseEvent) {
        marker.setOpacity(1.0);
      });
      marker.addListener('mouseout', function(mouseEvent) {
        marker.setOpacity(0.5);
    
      });
    
      var infoWindow = createInfoWindow(potholeData);
      // save infoWindow for later reference
      infoWindows[statesMap.get(getPotholeStateFor(potholeData))].push(infoWindow);
      // on click of marker, show infoWindow
      marker.addListener('click', function(mouseEvent) { 
        infoWindow.open(map, marker);
      });
      // add this to potholeMarkers
      potholeMarkers[statesMap.get(getPotholeStateFor(potholeData))].push(marker);  
      if (callback) return callback(null, marker);
      return marker;
    }
    

    snapPotholeCoordsToRoad()

    /* snaps potholes stored in potholeCoordinates to road
     * Parameters: 
     *  • potholeCollection : (Object<Array<PotholeData> >) the Collection of PotholeData to use
     *  • callback          : the function to call next
     */
    // TODO: refactor the body of this so as to use potholeCollection (preferrably instead of potholeCoordinates)
    function snapPotholeCoordsToRoad(potholeCollection, callback)
    {
        var DEBUG = false;
        // guarantee that callback is function
        if ((callback) && (typeof(callback) !== 'function')) throw new TypeError('callback is something, but not a function. Thrown from snapPotholeCoordsToRoad().');
        // for each element of potholeCollection
        if (DEBUG) console.log('potholeCollection === ' + JSON.stringify(potholeCollection, null, 't'));
        var keys = [];
        for (var key in potholeCollection)
        {
            if (typeof potholeCollection[key] !== 'function') keys.push(key);
        }
        for (var key in potholeCollection)
        {
            (function itr(k, m) { 
                if (typeof potholeCollection[k] === 'function') return;
                if (m === potholeCollection[k].length) return;
                if (DEBUG) console.log('potholeCollection.' + k + '[' + m + '] == ' + JSON.stringify(potholeCollection[k][m], null, 't'));
                // if element (PotholeData) not snapped to road
                if (!potholeCollection[k][m].isSnappedToRoad())
                {
                    // get road coordinates for element
                    getRoadCoordinates(potholeCollection[k][m])
                    // replace element's coordinates with those road coordinates
                    .done(function(newCoords) { 
                        potholeCollection[k][m].setCoordinates(newCoords.snappedPoints[0].location);
                        //debugger;
                        potholeCollection[k][m].isSnappedToRoad(true);
                        if (DEBUG) console.log('potholeCollection.' + k + '[' + m + '] == ' + JSON.stringify(potholeCollection[k][m], null, 't'));
                        if ((k === keys[keys.length - 1]) && (m === potholeCollection[k].length - 1) && (callback)) return callback(null, null, potholeCollection);
                        itr(k, m+1);
                    })
                }
                else
                {
                    if ((k === keys[keys.length - 1]) && (m === potholeCollection[k].length - 1) && (callback)) return callback(null, null,  potholeCollection);
                    itr(k, m+1);
                }
            })(key, 0);
        }
    }
    

    addPotholeMarkers()

    /* put all potholes on the map 
     * Parameters:
     *  • callback         : the function to call next
     *  • unsnappedPotholes: (<Object<Array<PotholeData> > ) collection of potholes with coordinates that have not been snapped to road
     *  • snappedPotholes  : (<Object<Array<PotholeData> > ) collection of potholes with coordinates that are snapped to road
     */
    function addPotholeMarkers(unsnappedPotholes, snappedPotholes, callback)
    {
        var DEBUG = false;
        // guarantee that callback is function
        if ((callback) && (typeof(callback) !== 'function')) throw new TypeError('callback is something, but not a function. Thrown from addPotholeMarkers().');
        // add all the markers for them to the map
        async.waterfall([
            function(cb) { 
                async.eachOf(unsnappedPotholes, function(value, key) {
                    // TODO: refactor this
                    async.eachOf(value, function (v, k) { 
                        if (DEBUG) console.log('dealing with unsnappedPotholes');
                        //console.assert(v.potholeState.toString() != '[object Object]', 'toString() override missing');
                        //v = revivePotholeState(v); // unnecessary, because addPotholeMarker() invokes getPotholeStateFor() to force the potholeState to be in the statesMap
                        addPotholeMarker(v, false);
                    })
                })
                cb(null);
            }, function(cb) {
                async.eachOf(snappedPotholes, function(value, key) { 
                    async.eachSeries(value, function(pothole, fn) { 
                        if (DEBUG) console.log('pothole == ' + JSON.stringify(pothole, null, 't'));
                        addPotholeMarker(pothole, 
                            true,
                            //pothole.isSnappedToRoad(),
                            fn); 
                    })
                })
                cb(null);
            }], function(err, results) {
                console.log('trying to center map');
    
                adjustMap();
                console.log('Map recentered');
                if (callback) { 
                    callback(err);
                }
            });
    
    
    }
    

    The driver function

    google.script.run.withSuccessHandler(function(data) { 
            async.waterfall([//fetchServerPotholeData,  // for some reason, this function is not receiving data
                function(callback) { 
                    fetchServerPotholeData(data, callback);
                },
                fetchCoords,
                snapPotholeCoordsToRoad,
                addPotholeMarkers
                ], function(err, result) { 
                    if (!err) { 
                        console.log('Everything successfully done. Enjoy your map!'); 
    
                }
                else 
                {
                    console.error(err);
                }
            }
        )
    }).withFailureHandler(console.log).getPotholeData();
    

    I’m trying to fix these bottlenecks but am not sure how.

    UPDATE

    I’m adding a link to the GitHub project itself that I created the other day, since this question’s been crickets since I asked it.

    Here is the HTML code to the app (maybe the script is wasting a lot of time loading the necessary tags):

    
    
      
        
        
        //ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js
        https://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.7.0/mustache.min.js
        https://cdn.jsdelivr.net/npm/async@2.5.0/dist/async.min.js
        <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
        <!--https://google-developers.appspot.com/_static/js/jquery-bundle.js-->
        //code.jquery.com/ui/1.12.1/jquery-ui.js
        <?!= include('mathFunctions'); ?>
        <?!=// include('Pothole'); ?>
        <?!= include('JavaScript'); ?>
        <?!= include('stylesheet'); ?>
      </head>
      <body>
        
    Legend
    </div>
    </body> </html>


    Get this bounty!!!

    #StackBounty: #javascript #jquery #html #tooltip Tooltip showing hidden values in table format on hover

    Bounty: 50

    My site is set up in the following way:

    4 user groups. Each user group can see different information. An example would be stock quantity for a store. So the user from London can’t see the stock availability for Manchester. This information is taken from the database for EACH item in stock. So if you have a list of 20 items, their individual values will be displayed.

    I would like to do the following:

    If I, or anyone I give permission to, hovers over the “In Stock” columm for their own store, a tooltip table must appear showing the current stock levels for the 3 other stores, for each individual product. So if I hover over item SKU-001, I will only see the stock availability for that item. I had an issue where it was displaying the whole list for each item.

    I was thinking of this:

    <table>
    <tr>
    <th>Store1></th>
    <th>Store2></th>
    <th>Store3></th>
    <th>Store4></th>
    </tr>
    <?php foreach($this->products as $product) { ?>
    <tr>
    <td id="stock1" title="myFunction">Stock of Item 1st store</td> *If I hover/mouseover here, another table must appear showing only store name and values of "#stock2, #stock3 and #stock4* for the stock item I am hovering on.
    <td id="stock2">Stock of Item 2nd store</td>
    <td id="stock3">Stock of Item 3rd store</td>
    <td id="stock4">Stock of Item 4th store</td>
    </tr>
    <?php } ?>
    </table>
    

    Here is some code I wrote:

    function myFunction() {
    var x = document.createElement("TABLE");
    x.setAttribute("id", "table10");
    document.body.appendChild(x);
    
    var y = document.createElement("TR");
    y.setAttribute("id", "myTr");
    document.getElementById("myTable").appendChild(y);
    
    var z = document.createElement("TD");
    var t = document.getElementByID("riyadhbalance").value();
    z.appendChild(t);
    document.getElementById("myTr").appendChild(z);
    

    However, for some reason this is not working. I have not found a way to include a tooltip. All the stock values are there for each individual item, so I just need to find a way to add the 3 values for the other stores and display them in a table format via a tooltip. That would be ideal.

    So basically the tooltip should show the 3 values of the stores which are currently not on display, as the other 3 values are hidden. The user can only see their store’s stock levels. But I would like to include this for myself as it would make it easier to view stock levels across the board.


    Get this bounty!!!

    #StackBounty: #javascript #jquery #instagram #instagram-api #instafeedjs instafeed.js stopped working: The access_token provided is inv…

    Bounty: 200

    I am using instafeed.js like so:

    var feed = new Instafeed({
            get: 'user',
            userId: 19191919191,
            limit: 9,
            accessToken: 'myaccesstokenhere',
            target: 'instagram',
            resolution: 'standard_resolution',
            after: function() {
                var el = document.getElementById('instagram');
                if (el.classList)
                    el.classList.add('show');
                else
                    el.className += ' ' + 'show';
            }
    });
    

    but I am getting this error:

    The access_token provided is invalid.
    

    I got the access_token by https://www.instagram.com/developer I registered my application and put the Client Secret as the accessToken and I got my userID from here https://smashballoon.com/instagram-feed/find-instagram-user-id/

    but its still saying The access_token provided is invalid. what am I doing wrong?


    Get this bounty!!!

    #StackBounty: #javascript #jquery #html #spring-boot #thymeleaf app context lost when changing the location in Thymeleaf

    Bounty: 50

    I have this piece of code in a Thymeleaf template, but I lose the application context when I am redirected

     $('#selectAuthorizedDriverId').change(
       function() {
          var link = "/deviceDriver/updateauthorizeddriver/" + $(this).val();
          $(location).attr('href',link);
    }); 
    

    This piece of code redirect the browser to the link, but without the application context, so I got a 404.
    To avoid this problem I normally use

    var link = /*[[@{/deviceDriver/updateauthorizeddriver/}]]*/ + "";
    

    and it works, but since here I’ve tried

    var link = /*[[@/deviceDriver/updateauthorizeddriver/}]]*/ + $(this).val() "";
    

    but it has not worked

    The URL I see is

    http://127.0.0.1:1234/deviceDriver/updateauthorizeddriver/

    and the URL valid should be

    http://127.0.0.1:1234/driversApp/deviceDriver/updateauthorizeddriver/


    Get this bounty!!!