Jquery code won't run loaded from footer, but run from console - javascript

I'm trying to get a value and pass it to a hidden input in order to send form data via $_POST. I have a dropdown button and the following code in order to update the value when a user select an option:
jQuery(document).ready(function($) {
var espSeleccionada = $('button[data-id="select-especialidad"]');
espSeleccionada.on("click", function() {
var x = $(this).text();
$('#boton-prueba').text(x);
});
});
The code is supposed to pass the value from one button to another, as shown in here the example, but, when I load the code from WordPress header/footer/theme nothing happens. Instead, when I write it on the console it works fine. There are no JS errors in console.
Please note that I'm using .text() to test if the code works, but it would have .val() before going live.
This is the button HTML:
<button type="button" class="btn dropdown-toggle btn-default" data-toggle="dropdown" data-id="select-especialidad" title="Hacienda" aria-expanded="false"><span class="filter-option pull-left">Hacienda</span></button>
Here is an example: https://fiddle.jshell.net/t9mvoxj5/
EDIT TO INCLUDE THE FULL CODE:
( function( $ ) {
var num_cols = 3,
container = $('#menu-preparadores-de-oposiciones-en'),
listItem = 'li',
listClass = 'sub-list';
container.each(function() {
var items_per_col = new Array(),
items = $(this).find(listItem),
min_items_per_col = Math.floor(items.length / num_cols),
difference = items.length - (min_items_per_col * num_cols);
for (var i = 0; i < num_cols; i++) {
if (i < difference) {
items_per_col[i] = min_items_per_col + 1;
} else {
items_per_col[i] = min_items_per_col;
}
}
for (var i = 0; i < num_cols; i++) {
$(this).append($('<ul ></ul>').addClass(listClass));
for (var j = 0; j < items_per_col[i]; j++) {
var pointer = 0;
for (var k = 0; k < i; k++) {
pointer += items_per_col[k];
}
$(this).find('.' + listClass).last().append(items[j + pointer]);
}
}
});
if ($("body").hasClass("page-id-64")) {
$('.tab-content').addClass('col-sm-9');
$('#custom-tabs-0').tabCollapse();
}
} ) ( jQuery );
jQuery(document).ready(function($) {
var espSeleccionada = $('button[data-id="select-especialidad"]');
espSeleccionada.on("click", function() {
var x = $(this).text();
$('#boton-prueba').text(x);
});
});

Well, the code is fine, the problem is that the target button[data-id="select-especialidad"] is being used by bootstrap-select and even if bootstrap-select loads before my code, it takes a few seconds (or at least a bit) to process the information.
So the code should be wrapped after a function that checks that the event has been loaded. This is the final code:
$('#select-especialidad').on('loaded.bs.select', function (e) {
var y = $(this).val();
$('#select-especialidad-hidden').val(y);
var espSeleccionada = $('button[data-id="select-especialidad"] > span.filter-option.pull-left');
espSeleccionada.on("click", function() {
var x = $(this).text();
$('#select-especialidad-hidden').val(x);
});
});
loaded.bs.select here more info on the bootstrap-select events.

Related

Right way to dynamically update table

I am getting data over websocket every 10 seconds and i am updating the cells using this function:
agentStatSocket.onmessage = function (e) {
data = JSON.parse(e.data);
//console.log(typeof(data));
for (var i = 0; i < data.length; i++) {
var inboundTd = '#' + data[i]['id'] + '-inbound';
var outboundTd = '#' + data[i]['id'] + '-outbound';
if (data[i]['inboundCalls'] != 0) {
$(inboundTd).html(data[i]['inboundCalls']);
}
if (data[i]['outboundCalls'] != 0) {
$(outboundTd).html(data[i]['outboundCalls']);
}
}
};
This is working pretty fine. However, I see some lag with the table being updated. Currently, there are only 150 rows in the table. I do not know what will be the latency if rows will become 1000 or more.
I have the following questions:
What is the correct approach to design these kinds of tables in which data is changing very frequently? I am not using any library like react or angular. This is plain jQuery.I am using dataTables
jQuery to enhance table view.
One thing to consider is that, in many cases, accessing an element based on an ID is usually a lot quicker in vanilla javascript compared to jquery.
A simple example of that is:
function jsTest() {
for (let i = 0; i < 1000; i++) {
document.getElementById("js").innerHTML = i;
}
}
function jqueryTest() {
for (let i = 0; i < 1000; i++) {
$("#jquery").html(i);
}
}
function startup() {
console.time("javascript");
jsTest();
console.timeEnd("javascript");
console.time("jquery");
jqueryTest();
console.timeEnd("jquery");
}
// For testing purposes only
window.onload = startup;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Javascript: <div id="js"></div>
Jquery: <div id="jquery"></div>
So, you could try changing your code to:
agentStatSocket.onmessage = function (e) {
data = JSON.parse(e.data);
//console.log(typeof(data));
for (var i = 0; i < data.length; i++) {
//var inboundTd = '#' + data[i]['id'] + '-inbound';
//var outboundTd = '#' + data[i]['id'] + '-outbound';
var inboundTd = data[i]['id'] + '-inbound';
var outboundTd = data[i]['id'] + '-outbound';
if (data[i]['inboundCalls'] != 0) {
//$(inboundTd).html(data[i]['inboundCalls']);
document.getElementById(inboundTd).innerHTML = data[i]['inboundCalls'];
}
if (data[i]['outboundCalls'] != 0) {
//$(outboundTd).html(data[i]['outboundCalls']);
document.getElementById(outboundTd).innerHTML = data[i]['outboundCalls'];
}
}
};
You can still use jquery for the rest of your code, if you wish, but simple updates to elements that can be targeted by ID are usually quicker with vanilla javascript.

How to create a function to be re-used for later within another function

I got this code:
$(document).ready(function(){
$(".nextForm").on('click',(function(){
//check criteria
if(selectedSlots.length < 1 ||$("#positionAppliedFor").get(0).value.length < 1 ||$("#maxAmountOfHours").get(0).value.length < 1){
//error messages and array
var errorForSlots= "<h5>Select at least one availability slot</h5>";
var errorForPosition = "<h5>Enter the position you wish to apply for<h5>";
var errorForHours = "<h5>Enter the amount of hours you would like to work<h5>";
var errors = [];
//add errors to array
if(selectedSlots.length < 1){errors.push(errorForSlots)};
if($("#positionAppliedFor").get(0).value.length < 1){errors.push(errorForPosition)};
if($("#maxAmountOfHours").get(0).value.length < 1){errors.push(errorForHours)};
//create message
var div = "<div id=\"sectionError\">";
if($("#sectionError").length > 0){$("#sectionError").html('')};
$(div).appendTo($(this).get(0).parentNode);
for(var i = 0; i < errors.length; i++){
$(errors[i]).appendTo($("#sectionError"));
console.log(errors[i]);}
$("</div>").appendTo($(this).get(0).parentNode);
} else {
$("#applicationDetails").slideUp();
$("#personalDetails").slideDown();
if($("#sectionError").length > 0){$("#sectionError").remove()};
}
console.log("function finished");
}));
It all works perfectly, however, I am trying to figure out how to create a function for
//create message
var div = "<div id=\"sectionError\">";
if($("#sectionError").length > 0){$("#sectionError").html('')};
$(div).appendTo($(this).get(0).parentNode);
for(var i = 0; i < errors.length; i++){
$(errors[i]).appendTo($("#sectionError"));
console.log(errors[i]);}
$("</div>").appendTo($(this).get(0).parentNode);
I am planning to re-use this for few other sections on my form and rather than copy/paste I would like to get some help on making my code tidier.
I did try:
function myFunction(){
//message code here
}
$(document).ready(function(){
$(".nextForm").on('click',(function(){
//check criteria
...
//add errors
...
//call func
myFunction();
(I also tried this.myFunction();)
...
}));
});
However, that ended up in TypeError and I don't know where to begin...
I am also concerned about the "this" in my message code so I am also not sure how to address that in my new function...
Admitedly I am a newbie at this and I do not exactly understand all the ins and outs, hopefully you will be able to help.
Maybe there is a better way of doing this?
Let me know your thought either way!
Thanks.
I have created a small reusable framework same as how jQuery is doing behind the scene to expose reusable functions. I didn't tested the append function properly,I just explaining how you can create your own reusable plugin to reuse across the project.
You can change the parameters and method name that you want to expose based on your functionality.
Also I would suggest you to move this code to a javascript file as a plugin and drag after the jquery script.
(function (global, $) {
//you can pass the jQuery object in to this IIFE
var DisplayError = function (elementId) {
return new DisplayError.init(elementId);
}
DisplayError.prototype = {
appendError: function (errors) {
var div = "<div id=\"" + this.elementId + " \">";
if ($(this.elementId).length > 0) {
$(this.elementId).html('')
};
$(div).appendTo($(this.elementId).get(0).parentNode);
for (var i = 0; i < errors.length; i++) {
$(errors[i]).appendTo($(this.elementId));
}
$("</div>").appendTo($(this.elementId).get(0).parentNode);
}
};
DisplayError.init = function (elementId) {
var self = this;
self.elementId = elementId;
}
DisplayError.init.prototype = DisplayError.prototype;
global.DisplayError = global.DisplayError = DisplayError;
}(window, jQuery));
You can write the code for clear the html directly in init function to ensure the element is clearing while initialize the instance itself.
You can invoke the method like below ,
var displayError=DisplayError("#sectionError")
displayError.appendError(["errorId"])
or
DisplayError("#sectionError").appendError(["errorId"])
Hope this helps
New Function
function generateMessage(arg1) {
//create message for each section
console.log("generating message");
var div = "<div id=\"sectionError\">";
if ($("#sectionError").length > 0) {
$("#sectionError").html('')
}
;$(div).appendTo($(arg1).parent());
for (var i = 0; i < errors.length; i++) {
$(errors[i]).appendTo($("#sectionError"));
console.log(errors[i]);
}
$("</div>").appendTo($(arg1).parent());
}
Changed old function
$(document).ready(function() {
$("#adbutnext").on('click', (function() {
//check criteria
if (selectedSlots.length < 1 || $("#positionAppliedFor").get(0).value.length < 1 || $("#maxAmountOfHours").get(0).value.length < 1) {
//error messages and array
var errorForSlots = "<h5>Select at least one availability slot</h5>";
var errorForPosition = "<h5>Enter the position you wish to apply for<h5>";
var errorForHours = "<h5>Enter the amount of hours you would like to work<h5>";
errors = [];
//add errors to array
if (selectedSlots.length < 1) {
errors.push(errorForSlots)
}
;if ($("#positionAppliedFor").get(0).value.length < 1) {
errors.push(errorForPosition)
}
;if ($("#maxAmountOfHours").get(0).value.length < 1) {
errors.push(errorForHours)
}
;
generateMessage(this);
} else {
$("#applicationDetails").slideUp();
$("#personalDetails").slideDown();
if ($("#sectionError").length > 0) {
$("#sectionError").remove()
}
;
}
console.log("function finished");
}
));
});

How do I create different button for each item in an array / JavaScript

Here's my code:
var never = [1,2,3,4,7];
function please () {
for (var i = 0; i < never.length; i++) {
document.getElementById("more").innerHTML = "<button>" + never[i] + "</button>";
}
}
I have a button in my HTML that invokes this function but it only creates a button for the last item (7). How can I create a different button for each one of the items in the array? Any help is appreciated.
The best way is to append created buttons in container.Each by each
var never = [1,2,3,4,7];
function please () {
var more=document.getElementById("more");
for (var i = 0; i < never.length; i++) {
var butt=document.createElement("button");
butt.innerHTML=never[i];
more.appendChild(butt);
}
}
By appending to innerHTML instead of assigning, like
var never = [1,2,3,4,7];
function please () {
for (var i = 0; i < never.length; i++) {
document.getElementById("more").innerHTML += "<button>" + never[i] + "</button>";
}
}
please();
<div id="more">
</div>

how to call javascript function on asp dropdown list [duplicate]

I have an ASP drop down list called and I need to load numbers 1 to 20 with 1 being selected as default. How to do this with javascript? I have a sample code but the drop down is not loading. Am I missing something?
<script>
function quantitydropdown() {
var ddl = document.getElementById('quantitydropdownid').getElementsByTagName("select")[0];
for (var i = 1; i <= 100; i++) {
var theOption = new Option;
theOption.text = i;
theOption.value = i;
ddl.options[i] = theOption;
}
}
</script>
<select id="quantitydropdownid" onchange="javascript:quantitydropdown();" runat="server" style="width: 200px;"></select>
So, when the document is ready, we populate the drop down:
// Set up event handler for when document is ready
window.addEventListener("DOMContentLoaded", function(){
// Get reference to drop down
var ddl = document.getElementById('quantitydropdownid');
for (var i = 1; i < 21; i++) {
var theOption = document.createElement("option");
theOption.text = i;
theOption.value = i;
// If it is the first option, make it be selected
i === 1 ? theOption.selected = "selected" : "";
ddl.options[i] = theOption;
}
});
#quantitydropdownid { width:200px; }
<select id="quantitydropdownid" runat="server"></select>
Please try with this code
-----------------------------------------
JS Code
----------------
$(document).ready(function(){
quantitydropdown();
})
function quantitydropdown()
{
for (var i = 1; i <= 20; i++)
{
$("#quantitydropdownid").append( $("<option></option>")
.attr("value", i)
.text(i)
);
}
}
Css Code
-----------
#quantitydropdownid { width:200px; }
HTML Code
-----------
<select id="quantitydropdownid" runat="server"></select>

Google Apps Script: How to get this code run after UI is closed?

This may seem a very newbie question, but I'm stuck with it. I've got this code to show a check list in a UI and insert the paragraphs of one or more documents into another target document:
var fact_list = [ ["Kennedy Inauguration", "politics", "tZwnNdFNkNklYc3pVUzZINUV4eUtWVWFSVEf"], ["Pericles’ Funeral Oration", "politics", "sdgrewaNkNklYc3pVUzZINUV4eUtW345ufaZ"], ["The Pleasure of Books", "culture", "1234rFszdgrfYc3pVUzZINUV4eU43usacd"], ["I Am The First Accused (Nelson Mandela)", "law", "34rsgadOsidjSZIswjadi95uydnfklsdks"] ];
function showList() {
var mydoc = SpreadsheetApp.getActiveSpreadsheet();
var app = UiApp.createApplication();
var panel = app.createVerticalPanel().setId('panel');
// Store the number of items in the array (fact_list)
panel.add(app.createHidden('checkbox_total', fact_list.length));
// add 1 checkbox + 1 hidden field per item
for(var i = 0; i < fact_list.length; i++){
var checkbox = app.createCheckBox().setName('checkbox_isChecked_'+i).setText(fact_list[i][0]);
var hidden = app.createHidden('checkbox_value_'+i, fact_list[i]);
panel.add(checkbox).add(hidden);
}
var handler = app.createServerHandler('submit').addCallbackElement(panel);
panel.add(app.createButton('Submit', handler));
app.add(panel);
mydoc.show(app);
}
function submit(e){
var numberOfItems = e.parameter.checkbox_total;
var itemsSelected = [];
// for each item, if it is checked / selected, add it to itemsSelected
for(var i = 0; i < numberOfItems; i++){
if(e.parameter['checkbox_isChecked_'+i] == 'true'){
itemsSelected.push(e.parameter['checkbox_value_'+i]);
}
}
var app = UiApp.getActiveApplication();
ScriptProperties.setProperties({'theses': itemsSelected}, true);
app.close();
return app;
}
function importTheses(targetDocId, thesesId, thesesType) { // adapted from Serge insas
var targetDoc = DocumentApp.openById(targetDocId);
var targetDocParagraphs = targetDoc.getParagraphs();
var targetDocElements = targetDocParagraphs.getNumChildren();
var thesesDoc = DocumentApp.openById(thesesId);
var thesesParagraphs = thesesDoc.getParagraphs();
var thesesElements = thesesDoc.getNumChildren();
var eltargetDoc=[];
var elTheses=[];
for( var j = 0; j < targetDocElements; ++j ) {
var targetDocElement = targetDoc.getChild(j);
// Logger.log(j + " : " + type);// to see targetDoc's content
eltargetDoc[j]=targetDocElement.getText();
if(el[j]== thesesType){
for( var k = 0; k < thesesParagraphs-1; ++k ) {
var thesesElement = thesesDoc.getChild(k);
elTheses[k] = thesesDoc.getText();
targetDoc.insertParagraph(j, elTheses[k]);
}
}
}
}
But when I call these functions inside my main function, I got a red message (in my language): service not available: Docs and, after the UI from showList() is closed, nothing more happens with my code (but I wanted the main functions continues to run). I call these functions this way:
if (theses == 1){
showList();
var thesesArrays = ScriptProperties.getProperty('theses');
for (var i = 0; i < thesesArrays.lenght(); i++){
var thesesId = ScriptProperties.getProperty('theses')[i][2];
var thesesType = ScriptProperties.getProperty('theses')[i][1];
importTheses(target, thesesId, thesesType);
}
}
showURL(docName, link); // Shows document name and link in UI
So, how can I fix that? How can I get the code run until the line showURL(docName, link);?
showList();
This function creates only Ui.
You are setting the script properties only in the Server Handler which executes on the click of submit button. Since then:
ScriptProperties.getProperty('theses');
will hold nothing. So you need to call these lines:
var thesesArrays = ScriptProperties.getProperty('theses');
for (var i = 0; i < thesesArrays.lenght(); i++){
var thesesId = ScriptProperties.getProperty('theses')[i][2];
var thesesType = ScriptProperties.getProperty('theses')[i][1];
importTheses(target, thesesId, thesesType);
}
Inside server handler or put them inside a method and call the method from the server Handler.

Categories

Resources