Show all tabs content vanilla js - javascript

How can I change this javascript code, that when I click on "Green" I want the content from all tabs to be displayed? https://codepen.io/wangel13/pen/OXBrRp
'use strict';
function Tabs() {
var bindAll = function() {
var menuElements = document.querySelectorAll('[data-tab]');
for(var i = 0; i < menuElements.length ; i++) {
menuElements[i].addEventListener('click', change, false);
}
}
var clear = function() {
var menuElements = document.querySelectorAll('[data-tab]');
for(var i = 0; i < menuElements.length ; i++) {
menuElements[i].classList.remove('active');
var id = menuElements[i].getAttribute('data-tab');
document.getElementById(id).classList.remove('active');
}
}
var change = function(e) {
clear();
e.target.classList.add('active');
var id = e.currentTarget.getAttribute('data-tab');
document.getElementById(id).classList.add('active');
}
bindAll();
}
var connectTabs = new Tabs();

Take a look at this:
'use strict';
function Tabs() {
var bindAll = function() {
var menuElements = document.querySelectorAll('[data-tab]');
for(var i = 0; i < menuElements.length ; i++) {
menuElements[i].addEventListener('click', change, false);
}
}
var clear = function() {
var menuElements = document.querySelectorAll('[data-tab]');
for(var i = 0; i < menuElements.length ; i++) {
menuElements[i].classList.remove('active');
var id = menuElements[i].getAttribute('data-tab');
document.getElementById(id).classList.remove('active');
}
}
function makeAllActive() {
var tabs = document.querySelectorAll('.b-tab');
Array.from(tabs).map(item => {
item.classList.add('active');
});
}
var change = function(e) {
clear();
e.target.classList.add('active');
var id = e.currentTarget.getAttribute('data-tab');
if(id === "green") {
makeAllActive();
return;
}
document.getElementById(id).classList.add('active');
}
bindAll();
}
var connectTabs = new Tabs();

Related

How to set closure to capsule global variable

I have following functions,in which I can set prompt when someone leave page while inputting some values.
My consern is how to encapsule checkFlag. in this case, checkFlag is treated as global variables.
So that it is somewhat inconvenient.
let checkFlag = false;
const onBeforeunloadHandler = function(e) {
var msg = '';
e.returnValue = msg;
};
const formAlert = function() {
if(!checkFlag) {
window.addEventListener('beforeunload', onBeforeunloadHandler);
for(var i = 0; i < checkValue.length; i++) {
checkValue[i].removeEventListener('input', formAlert);
checkValue[i].removeEventListener('change', formAlert);
}
checkFlag = true;
}
};
(() => {
let checkValue = document.querySelectorAll( "input[form='test'], textarea[form='test']");
let submitBtn = document.querySelector('button[type="button"]');
for(var i = 0; i < checkValue.length; i++) {
checkValue[i].addEventListener('input', formAlert);
checkValue[i].addEventListener('change', formAlert);
}
submitBtn.addEventListener('click', function() {
window.removeEventListener('beforeunload', onBeforeunloadHandler);
});
})();
If someone has opinion, will you please let me know.
Thanks
There's no need for anything in the outer scope. You can put it all into the IIFE.
(() => {
let checkFlag = false;
const onBeforeunloadHandler = function(e) {
var msg = '';
e.returnValue = msg;
};
const formAlert = function() {
if(!checkFlag) {
window.addEventListener('beforeunload', onBeforeunloadHandler);
for(var i = 0; i < checkValue.length; i++) {
checkValue[i].removeEventListener('input', formAlert);
checkValue[i].removeEventListener('change', formAlert);
}
checkFlag = true;
}
};
let checkValue = document.querySelectorAll( "input[form='test'], textarea[form='test']");
let submitBtn = document.querySelector('button[type="button"]');
for(var i = 0; i < checkValue.length; i++) {
checkValue[i].addEventListener('input', formAlert);
checkValue[i].addEventListener('change', formAlert);
}
submitBtn.addEventListener('click', function() {
window.removeEventListener('beforeunload', onBeforeunloadHandler);
});
})();
(() => {
let checkFlag = false;
const onBeforeunloadHandler = function(e) {
var msg = '';
e.returnValue = msg;
};
const formAlert = function() {
if(!checkFlag) {
window.addEventListener('beforeunload', onBeforeunloadHandler);
for(var i = 0; i < checkValue.length; i++) {
checkValue[i].removeEventListener('input', formAlert);
checkValue[i].removeEventListener('change', formAlert);
}
checkFlag = true;
}
};
let checkValue = document.querySelectorAll( "input[form='test'], textarea[form='test']");
let submitBtn = document.querySelector('button[type="button"]');
for(var i = 0; i < checkValue.length; i++) {
checkValue[i].addEventListener('input', formAlert);
checkValue[i].addEventListener('change', formAlert);
}
submitBtn.addEventListener('click', function() {
window.removeEventListener('beforeunload', onBeforeunloadHandler);
});
})();

TinyMce 5 setcontent unable to set html properly

I am writing a tinymce custom plugin called Mergetable. which will merger two user selected table.
Problem statement:
TinyMce is not allowing to select two table , by using shift and mouse I can select content of the table. So I can't use tinmce.activeeditor.selection.getNode() method instead using tinmce.activeeditor.selection.getContent().
Form getcontent() method I am getting proper html of both table. After do some operation while setting content using tinmce.activeeditor.selection.setContent() both table merged properly but two more table with empty td created one in top and one in bottom . Please see below plugin code.
code:
(function () {
var mergeTable = (function () {
'use strict';
tinymce.PluginManager.add("mergeTable", function (editor, url) {
function Merge(){
var selectedhtml=editor.selection.getContent();
//using getContent() as getnode returning body node
var dv=document.createElement('div');
dv.innerHTML= selectedhtml;
var tableElements = dv.getElementsByTagName('TABLE');
if (tableElements.length == 2) {
var tableOne = tableElements[0];
var tableTwo = tableElements[1];
var tempTable = null;
var offsetLeft = tableOne.offsetLeft;
var offsetTop = tableOne.offsetTop;
var elem = tableElements[0];
if (tableOne.nodeName == "TABLE" && tableTwo.nodeName == "TABLE") {
for (var r = 0; r < tableTwo.rows.length; r++) {
var newTR = tableOne.insertRow(tableOne.rows.length);
for (var i = 0; i < tableTwo.rows[r].cells.length; i++) {
var newTD = newTR.insertCell()
newTD.innerHTML = tableTwo.rows[r].cells[i].innerHTML;
newTD.colSpan = tableTwo.rows[r].cells[i].colSpan;
newTD.rowSpan = tableTwo.rows[r].cells[i].rowSpan;
newTD.style.cssText = tableTwo.rows[r].cells[i].style.cssText;
if (tableOne.style.border != "") {
newTD.style.border = "1px dotted #BFBFBF"
}
}
}
tableTwo.remove();
console.log(dv.innerHTML);
editor.selection.setContent(dv.innerHTML);
editor.nodeChanged();
}
else {
alert("Please select two tables");
}
}
}
editor.ui.registry.addButton('mergeTable', {
text: "Merge Table",
onAction: function(){ Merge();}
});
});
}());
}());
I am able to fix my problem by using some work around . Instead use setContent() method. I have remove selected content and use insertContent().
Please find working code below.
(function () {
var mergeTable = (function () {
'use strict';
tinymce.PluginManager.add("mergeTable", function (editor, url) {
var cmd = function (command) {
return function () {
return editor.execCommand(command);
};
};
function Merge(){
var selectedhtml=editor.selection.getContent();
var dv=document.createElement('div');
dv.innerHTML= selectedhtml;
var tableElements = dv.getElementsByTagName('TABLE');
if (tableElements.length == 2) {
var tableOne = tableElements[0];
var tableTwo = tableElements[1];
var tempTable = null;
var tableOneMaxCell=0
var tabletwoMaxCell=0
var tempCellcount=0
var tableOneRowcount=tableOne.rows.length;
tableOne.querySelectorAll("tr").forEach(function(e){
tempCellcount= e.querySelectorAll("td").length ;
if(tempCellcount>tableOneMaxCell)
{
tableOneMaxCell=tempCellcount;
}
});
tableTwo.querySelectorAll("tr").forEach(function(e){
tempCellcount= e.querySelectorAll("td").length ;
if(tempCellcount>tabletwoMaxCell)
{
tabletwoMaxCell=tempCellcount;
}
});
if (tableOne.nodeName == "TABLE" && tableTwo.nodeName == "TABLE") {
for (var r = 0; r < tableTwo.rows.length; r++) {
var newTR = tableOne.insertRow(tableOne.rows.length);
for (var i = 0; i < tableTwo.rows[r].cells.length; i++) {
var newTD = newTR.insertCell()
newTD.innerHTML = tableTwo.rows[r].cells[i].innerHTML;
newTD.colSpan = tableTwo.rows[r].cells[i].colSpan;
newTD.rowSpan = tableTwo.rows[r].cells[i].rowSpan;
newTD.style.cssText = tableTwo.rows[r].cells[i].style.cssText;
if (tableOne.style.border != "") {
newTD.style.border = "1px dotted #BFBFBF"
}
if(i==tableTwo.rows[r].cells.length-1 && tableOneMaxCell>tabletwoMaxCell){
newTD.colSpan = tableTwo.rows[r].cells[i].colSpan + (tableOneMaxCell-tabletwoMaxCell);
}
}
}
for( var t1=0; t1<tableOneRowcount; t1++ ){
var celllen=tableOne.rows[t1].cells.length;
tableOne.rows[t1].cells[celllen-1].colSpan=tableOne.rows[t1].cells[celllen-1].colSpan+(tabletwoMaxCell-tableOneMaxCell)
}
tableTwo.remove();
// cmd('mceTableDelete');
// var selObj = editor.selection;
// var selstartRange = selObj.getStart();
// var selectendRange= selObj.getEnd();
// var selrng=selObj.getRng();
// console.log(selstartRange);
// console.log(selectendRange);
// editor.execCommand('mceTableDelete');
// selObj.removeAllRanges();
editor.selection.getSelectedBlocks().forEach(function(elm){
elm.remove();
});
// selObj.setRng(selrng,true);
editor.insertContent(dv.innerHTML);
editor.nodeChanged();
}
else {
editor.notificationManager.open({
text: 'Please select two table.',
type: 'error'
});
}
}
else {
editor.notificationManager.open({
text: 'Please select two table.',
type: 'error'
});
}
}
editor.ui.registry.addButton('mergeTable', {
text: "MergeTable",
onAction: function(){ Merge();}
});
});
}());
}());

How to get variable data by id

Recently i have used code in project that is still working it it http://kreditka.testovi-site.pw. But when i tried to reuse javascript the default rules js got broken and i got an error in console explaining that varibale cannot be found. Is it somehow related that sme o the code is not resusable and each line should be rewritten one by one for defferent projects?
(function () {
console.log("()");
"use strict";
var polosa = document.querySelector("#polosa");
alert(polosa);
var x = document.querySelectorAll("#slide1");
var o;
for (o = 0; o < x.length; o++) {
x[o].style.left = o*300+"px";
}
var x = document.querySelectorAll("#slide");
var a;
for (a = 0; a < x.length; a++) {
x[a].style.left = a*300+"px";
}
var doc = document.querySelectorAll('.btn-click');
for (var i = 0; i < doc.length; i++) {
doc[i].addEventListener("click", highlightThis, true);
}
var doc1 = document.querySelectorAll('.btn1-click');
for (var j = 0; j < doc.length; j++) {
doc1[j].addEventListener("click", highlightThis1, true);
}
var polosa = document.querySelector('#polosa');
polosa.style.left = '0px';
var left = 0;
var sliderItem = document.querySelector('#slide');
function highlightThis(event) {
console.log("highlightThis");
var currentActiveButton = document.querySelector(".btn-click.btn-slide-active");
currentActiveButton.classList.toggle("btn-slide-active");
event.target.classList.toggle("btn-slide-active");
console.log(event.target.dataset.value);
shiftSlide({
prev: currentActiveButton.dataset.value,
next: event.target.dataset.value
});
}
function highlightThis1(event) {
console.log("highlightThis1");
var currentActiveButton1 = document.querySelector(".btn1-click.btn-slide-active");
currentActiveButton1.classList.toggle("btn-slide-active");
event.target.classList.toggle("btn-slide-active");
console.log(event.target.dataset.value);
shiftSlide1({
prev: currentActiveButton1.dataset.value,
next: event.target.dataset.value
});
}
function shiftSlide(obj) {
var polosa = document.querySelector('#polosa');
console.log("shiftSlide");
var currentSliderPosition = parseInt(polosa.style.left);
if (obj.prev === obj.next) {
return
} else {
var left = (obj.prev - obj.next) * 300;
polosa.style.left = currentSliderPosition + left + "px";
}
}
function shiftSlide1(obj) {
var polosa = document.querySelector('#polosa1');
console.log("shiftSlide");
var currentSliderPosition = parseInt(polosa1.style.left);
if (obj.prev === obj.next) {
return
} else {
var left = (obj.prev - obj.next) * 300;
polosa1.style.left = currentSliderPosition + left + "px";
}
}
})();

Run function inside another function

If I run this code:
var alts = {};
$('.grid ul').find('.lista-produtos:visible').each(function(){
var classes2 = $(this).attr('class').split(' ');
for (var i = 0; i < classes2.length; i++) {
var matches2 = /^tipo\-(.+)/.exec(classes2[i]);
if (matches2 != null) {
var produto2 = matches2[1];
}
}
if(!alts[classes2]){
alts[classes2] = true;
$('ul.filters').append('<li class="filter-produto">'+ produto2 +'</li>');
}
});
as a function, like this:
function tipoProduto(){
var alts = {};
$('.grid ul').find('.lista-produtos:visible').each(function(){
var classes2 = $(this).attr('class').split(' ');
for (var i = 0; i < classes2.length; i++) {
var matches2 = /^tipo\-(.+)/.exec(classes2[i]);
if (matches2 != null) {
var produto2 = matches2[1];
}
}
if(!alts[classes2]){
alts[classes2] = true;
$('ul.filters').append('<li class="filter-produto">'+ produto2 +'</li>');
}
});
}
and call it here:
$('.list-group-item').click(function(){
var classes1 = $(this).attr('class').split(' ');
for (var i = 0; i < classes1.length; i++) {
var matches1 = /^ctrl\-(.+)/.exec(classes1[i]);
if (matches1 != null) {
var marca1 = matches1[1];
}
}
$(this).addClass("active");
$('.list-group-item').not(this).removeClass("active");
if ($('.todos-produtos').hasClass("active")) {
$('.lista-produtos').hide();
$('.' + marca1).show();
}
else {
var produto1 = $('li.filter-produto.active').text();
$('.lista-produtos').not('.' + marca1 + '.tipo-' + produto1).hide();
$('.' + marca1 + '.tipo-' + produto1).show()
}
tiposProduto(); // CALLING IT HERE //
});
});
then this code below doesn't work:
$(document).ready(function(){
$('.filter-produto').click(function() {
var classes3 = $('.list-group-item.active').attr('class').split(' ');
for (var i = 0; i < classes3.length; i++) {
var matches3 = /^ctrl\-(.+)/.exec(classes3[i]);
if (matches3 != null) {
var marca2 = matches3[1];
}
}
$(this).addClass("active");
$('.filter-produto').not(this).removeClass("active");
if ($(this).hasClass("todos-produtos")) {
$('.' + marca2).show();
}
else {
var produto3 = $(this).text();
$(".lista-produtos").not('.tipo-' + produto3).hide();
$('.' + marca2 + '.tipo-' + produto3).show();
}
});
});
but if I change the 1st code to this:
$(document).ready(function(){
var alts = {};
$('.grid ul').find('.lista-produtos:visible').each(function(){
var classes2 = $(this).attr('class').split(' ');
for (var i = 0; i < classes2.length; i++) {
var matches2 = /^tipo\-(.+)/.exec(classes2[i]);
if (matches2 != null) {
var produto2 = matches2[1];
}
}
if(!alts[classes2]){
alts[classes2] = true;
$('ul.filters').append('<li class="filter-produto">'+ produto2 +'</li>');
}
});
});
then the 4th code works again.
The problem is I need the code above as a function, like I showed on the 2nd and 3rd examples.
Thanks!
Thanks for the few replies. I found out the problem.
Appended objects weren't being recognized by the functions. That's why $('.filter-produto').click(function() { wasn't working.

JavaScript continue label scope

Map.prototype.updateMap = function (vehicles) {
nextVehicle:
for (var i = 0; i < vehicles.length; i++) {
for (var j = 0; j < this.oldVehicles.length; j++) {
var vehicle = vehicles[i];
var oldVehicle = this.oldVehicles[j];
if (vehicle.registration == oldVehicle.registration) {
oldVehicle.getPosition(function(latLng) {
if (vehicle.latitude != oldVehicle.lat) {
var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
oldVehicle.setPosition(newPos);
}
continue nextVehicle;
});
}
}
}
};
The code above does not work. I have a feeling this is to do with scope, I can't reach the nextVehicle label from inside the oldVehicle.getPosition method. How can I get around this?
Separate the matching logic from the update logic.
Map.prototype.updateMap = function (vehicles) {
// Only need to look up array lengths once
var vehiclesLength = vehicles.length,
oldVehiclesLength = this.oldVehicles.length;
for (var i = 0; i < vehiclesLength; i++) {
var vehicle = vehicles[i];
var oldVehicle = null;
// Find oldVehicle
for (var j = 0; j < oldVehiclesLength; j++) {
if (vehicle.registration == oldVehicle[j].registration) {
oldVehicle = oldVehicles[j];
break;
}
}
// Check for update if found
if (oldVehicle){
// Create closure for async callbacks
(function(oldV, lat,lng){
oldV.getPosition(function(latLng) {
if (lat != oldV.lat) {
var newPos = new plugin.google.maps.LatLng(lat,lng);
oldV.setPosition(newPos);
}
});
})(oldVehicle, vehicle.latitude, vehicle.longitude);
}
}
};
Just move the continue nextVehicle; line from inside the callback to immediately following the call to oldVehicle.getPosition(...):
Map.prototype.updateMap = function (vehicles) {
nextVehicle:
for (var i = 0; i < vehicles.length; i++) {
for (var j = 0; j < this.oldVehicles.length; j++) {
var vehicle = vehicles[i];
var oldVehicle = this.oldVehicles[j];
if (vehicle.registration == oldVehicle.registration) {
oldVehicle.getPosition(function(latLng) {
if (vehicle.latitude != oldVehicle.lat) {
var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
oldVehicle.setPosition(newPos);
}
});
continue nextVehicle;
}
}
}
};
This assumes the call to getPosition is a synchronous operation.
Edit:
Now if getPosition is asynchronous, you will need to use an asynchronous loop:
Something along this line might do the trick:
Map.prototype.updateMap = function (vehicles) {
var i = 0, j = -1, self = this;
var updatePosition = function() {
j++;
if (j == self.oldVehicles.length) {
j = 0;
i++;
}
if (i === vehicles.length) {
return; // We're done
}
var vehicle = vehicles[i];
var oldVehicle = self.oldVehicles[j];
if (vehicle.registration !== oldVehicle.registration) {
updatePosition();
}
else {
oldVehicle.getPosition(function(latLng) {
if (vehicle.latitude != oldVehicle.lat) {
var newPos = new plugin.google.maps.LatLng(vehicle.latitude, vehicle.longitude);
oldVehicle.setPosition(newPos);
updatePosition();
}
});
}
};
updatePosition();
};

Categories