This question is the following of that. At initialization of the page, the buttons are not "bridged", and becomes when the user clicks on the blue button with the icon inside.
Conditions :
If 2 buttons are bridged (action when clicked on blue button), the other must become bridged (join with numbers around) [this works]
After that, if the user clicks on any button, the 3 buttons have to separate from numbers around
I have this HTML code (using Bootstrap 3) :
<div class="col-sm-12 interfacesBridge">
<h3 class="text-info">Interfaces</h3>
<div class="col-sm-4">
<div class="input-group input-group-lg">
<div class="input-group-btn">
<button type="button" class="btn btn-default bRLeft" disabled="disabled" style="margin-right: 15px !important;">3</button>
<button type="button" class="btn btn-info linkInterfaces" data-interfaces="3-4"><i class="fa fa-chain-broken"></i></button>
<button type="button" class="btn btn-default bRRight" disabled="disabled" style="margin-left: 15px !important;">4</button>
</div>
</div>
</div>
<div class="col-sm-4">
<div class="input-group input-group-lg">
<div class="input-group-btn">
<button type="button" class="btn btn-default bRLeft" disabled="disabled" style="margin-right: 15px !important;">3</button>
<button type="button" class="btn btn-info linkInterfaces" data-interfaces="3-5"><i class="fa fa-chain-broken"></i></button>
<button type="button" class="btn btn-default bRRight" disabled="disabled" style="margin-left: 15px !important;">5</button>
</div>
</div>
</div>
<div class="col-sm-4">
<div class="input-group input-group-lg">
<div class="input-group-btn">
<button type="button" class="btn btn-default bRLeft" disabled="disabled" style="margin-right: 15px !important;">4</button>
<button type="button" class="btn btn-info linkInterfaces" data-interfaces="4-5"><i class="fa fa-chain-broken"></i></button>
<button type="button" class="btn btn-default bRRight" disabled="disabled" style="margin-left: 15px !important;">5</button>
</div>
</div>
</div>
</div>
And this jQuery code :
function setBridged(selector) {
selector.addClass('bridged');
selector.prev().animate({'marginRight': '0', 'marginLeft': '15px'}, 1000);
selector.next().animate({'marginLeft': '0'}, 1000);
selector.find('i').removeClass().addClass('fa fa-link');
}
function unsetBridged(selector) {
selector.removeClass('bridged');
selector.prev().animate({'marginRight': '15px', 'marginLeft': '0'}, 1000);
selector.next().animate({'marginLeft': '15px'}, 1000);
selector.find('i').removeClass().addClass('fa fa-chain-broken');
}
$(document).ready(function () {
$('.linkInterfaces').click(function () {
if ($(this).find('i').hasClass('fa-chain-broken')) {
setBridged($(this));
} else {
unsetBridged($(this));
}
if ($('.interfacesBridge .bridged').length >= 2) {
$('.linkInterfaces:not(.bridged)').trigger('click', function() {
setBridged($(this));
});
}
});
});
I tried many things to get there, but that's me stuck.
Please see the jsfiddle associated.
After observing the conditions, the click event's trigger timing is:
When something bridged, if there's more than 2 (include self), then bridge every one that is not bridge yet.
When something unbridged, if there's still more than 2 bridged, which means prev state is all bridged, unbridge all.
So you can change the logic to:
$('.linkInterfaces').click(function () {
if ($(this).find('i').hasClass('fa-chain-broken')) {
//targetFunc = setBridged;
setBridged($(this));
if ($('.interfacesBridge .bridged').length >= 2) {
$('.linkInterfaces:not(.bridged)').trigger('click');
}
} else {
unsetBridged($(this));
if ($('.interfacesBridge .bridged').length >= 2) {
$('.interfacesBridge .bridged').trigger('click');
}
}
});
Altered jsfiddle.
It's also possible to extract the logic out in this case, but note if the condition to bridge/unbridge all becomes different(e.g: >= 2 to bridge, <= 1 to unbridge), than the first one would be better to separate the logic.
$('.linkInterfaces').click(function () {
var relatedTargets;
if ($(this).find('i').hasClass('fa-chain-broken')) {
setBridged($(this));
relatedTargets = '.linkInterfaces:not(.bridged)';
} else {
unsetBridged($(this));
relatedTargets = '.linkInterfaces.bridged';
}
// When bridged element is more than 2 when clicked, we need to either link all, or unlink all.
if ($('.interfacesBridge .bridged').length >= 2) {
$(relatedTargets).trigger('click');
}
});
And note the .trigger's 2nd or later params would be passed to event handler, but won't trigger, so in your original code, that passed in function won't take effect unless you call it in your event handler.
Related
I am trying to implement a dynamic increment/decrement counter. Here is how it should work:
I have an 'ADD' button. When i click on this, the same should disappear and a minus button, number input, plus button should appear. Clicking on "+" should increment the counter on the "cart" and clicking on "-" should decrement.
Below is html mycode
<body>
<div id="page-wrap">
<h1>Cart Inc Dec</h1>
<a href="#" class="btn btn-info btn-lg mt-5 mr-5 mb-5">
<span class="glyphicon glyphicon-shopping-cart"><span id="itemCount"></span></span> Check Out
</a>
<br>
<a id="btnAddItem" class="btn btn-primary float-right mt-5 mb-5 mr-5">ADD</a>
<div class="addItem">
</div>
</div>
</body>
Jquery:
<script>
var addElement = 0;
$(document).ready(function(){
$("#btnAddItem").on("click", function (event) {
if(addElement==0){
$(".addItem").append(('<button type="button" class="counter decrease">-</button><input type="text" size="5" id="txtCounter" /><button type="button" class="counter increase">+</button>'));
}
addElement++;
});
var $input = $("#txtCounter");
// Initialise the value to 0
$input.val(0);
debugger;
// Increment/decrement count
$(".counter").click(function(){
console.log('here i am');
if ($(this).hasClass('increase'))
$input.val(parseInt($input.val())+1);
else if ($input.val()>=1)
$input.val(parseInt($input.val())-1);
});
});
</script>
Now the problem is after i add the dynamic +, text input counter, - controls, nothing happens when i click on + or minus. console.log inside $(".counter").click(function() is not giving anything.
Am i missing something??
You can do it like this: Adjust the $(".counter").click(function() {}); to $(document).on("click", ".counter", function(){}); as the element with the class counter isn't there when the page is initially loaded and therefore the click() event has to be delegated from a static parent element to the added counter element using on(). Move then the variable declaration var $input = $("#txtCounter"); inside this click function as the element with the id txtCounter isn't there when the page is initally loaded and move the initialization $("#txtCounter").val(0); after appending it.
var addElement = 0;
$(document).ready(function() {
$("#btnAddItem").on("click", function(event) {
if (addElement == 0) {
$(".addItem").append(('<button type="button" class="counter decrease">-</button><input type="text" size="5" id="txtCounter" /><button type="button" class="counter increase">+</button>'));
// Initialise the value to 0
$("#txtCounter").val(0);
}
addElement++;
});
// Increment/decrement count
$(document).on("click", ".counter", function() {
var $input = $("#txtCounter");
if ($(this).hasClass('increase')) {
$input.val(parseInt($input.val()) + 1);
} else if ($input.val() >= 1) {
$input.val(parseInt($input.val()) - 1);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="page-wrap">
<h1>Cart Inc Dec</h1>
<a href="#" class="btn btn-info btn-lg mt-5 mr-5 mb-5">
<span class="glyphicon glyphicon-shopping-cart"><span id="itemCount"></span></span> Check Out
</a>
<br>
<a id="btnAddItem" class="btn btn-primary float-right mt-5 mb-5 mr-5">ADD</a>
<div class="addItem">
</div>
</div>
You can change the script and try something like below:
var addElement = 0;
var myCounter= function(action){
var val = document.getElementById("txtCounter").value;
val = parseInt(val);
if(action == 2){ //Increase
document.getElementById("txtCounter").value=val+1;
}else if(val > 1){
document.getElementById("txtCounter").value=val-1;
}
};
$(document).ready(function(){
$("#btnAddItem").on("click", function (event) {
if(addElement==0){
$(".addItem").append(('<button type="button" onclick="myCounter(1);" class="counter decrease">-</button><input type="text" size="5" id="txtCounter" value="0" /><button type="button" onclick="myCounter(2);" class="counter increase">+</button>'));
}
addElement++;
});
});
I am trying to get the Id of a button for DOM manipulation. I have a group of buttons and I want to get Id of only the button which is clicked.
My Code is:-
<div class="row mb-5" id="widthRow">
<div class="col-md-12 mx-auto">
<p class="text-info font-weight-bold">Width :-</p>
<button class="btn btn-sm btn-success w" id="200">200px</button>
<button class="btn btn-sm btn-success w" id="400">400px</button>
<button class="btn btn-sm btn-success w" id="600">600px</button>
<button class="btn btn-sm btn-success w" id="800">800px</button>
</div>
</div>
I tried searching on stack overflow and got an answer with code:-
var buttons = document.getElementsByTagName("button");
var buttonsCount = buttons.length;
for (var i = 0; i <= buttonsCount; i += 1) {
buttons[i].onclick = function(e) {
alert(this.id);
};
}
});
But when I use it on my page, I get the error:-
https://imgur.com/a/cnLrVGp.
Note:- (I also used this code with getElementsByClassName. )
I tried searching for this error also. And some said that DOM is not loaded before manipulation. So, I added defer to script and also added
window.addEventListener("DOMContentLoaded", function() {}
But nothing helped. Kindly help. Thanks in advance.
Probably you are executing your code before the DOM is fully loaded. You can either place the code at the bottom of the body or wrap your code with DOMContentLoaded:
The DOMContentLoaded event fires when the initial HTML document has been completely loaded and parsed, without waiting for stylesheets, images, and subframes to finish loading.
Please Note: As getElementsByTagName() returns HTMLCollection which maintains 0 based indexing, you are iterating your loop more than the length of buttons, change <= to <.
<script>
document.addEventListener('DOMContentLoaded', (event) => {
var buttons = document.getElementsByTagName("button");
var buttonsCount = buttons.length;
for (let i = 0; i < buttonsCount; i++) {
buttons[i].onclick = function(e) {
alert(this.id);
};
}
});
</script>
<div class="row mb-5" id="widthRow">
<div class="col-md-12 mx-auto">
<p class="text-info font-weight-bold">Width :-</p>
<button class="btn btn-sm btn-success w" id="200">200px</button>
<button class="btn btn-sm btn-success w" id="400">400px</button>
<button class="btn btn-sm btn-success w" id="600">600px</button>
<button class="btn btn-sm btn-success w" id="800">800px</button>
</div>
</div>
I made a "Add new shipment" button that creates a whole div that includes like 4 fields and a 2nd submit button under all that. that 2nd submit button is supposed to post this new div onto the page and add it to db but I am having trouble selecting the fields and selecting the new submit button. I think this is because the page is already loaded from the beginning, so this new div cannot be selected anymore? Here is my HTML that is created from the "Add new shipment" button:
// adds new shipment
const ADD_SHIPMENT_GRAY = function (){
return
<div class="shipment panel panel-success col-xs-2">
<div class="shipmentblocks row">
<div class="idzone btn-block classificationline">
<!-- label ---->
<input type="text" class="customer btn btn-default btn-xs col-xs-12" placeholder="Customer"><strong id="customertext"></strong></button>
<!-- contents -->
<input type="text" class="btn btn-default btn-xs col-xs-12" placeholder="File Number">
<strong class="boldedlabels" id="filenumber"></strong>
<span class="labelcontents"></span>
</button>
<button type="button" class="etd btn btn-default btn-xs col-xs-12" placeholder="ETD" id="etd">
<strong class="boldedlabels"></strong>
<span class="labelcontents" id="etddatepicker">ETD</span>
</button>
<button type="button" class="eta btn btn-default btn-xs col-xs-12" placeholder="ETA" id="eta">
<strong class="boldedlabels"></strong>
<span class="labelcontents" id="etadatepicker">ETA</span>
</button>
<button type="button" class="shipmentsubmission btn btn-default btn-xs col-xs-12">
<strong class="boldedlabels eta"></strong>
<span class="labelcontents" id="submitnewshipment">Submit</span>
</button>
</div>
</div>
</div>;
}
Here is my javascript code that executes the above code:
const SCRIPTS = function (){
$(function(){
const addshipment = $("#addshipment"),
labelsubmission = $(".labelsubmission"),
shipment = $(".shipment"),
shipmentblocks = $(".shipmentblocks"),
idzone = $(".idzone"),
etd = $(".etd"),
addsubmit = $("#addsubmit"),
zzz = $("#zzz"), // div to keep maximum new shipment as 1
submitnewshipment = $("#submitnewshipment"), // button to submit the new shipment
// Add New Shipment
addshipment.click(() => { // in console, indexes closer to 0 (ex: index [0]) = newer
//$(".shipment:first").before(ADD_SHIPMENT_GRAY());
// add new shipment green block
$("#zzz").html(ADD_SHIPMENT_GRAY());
});
})
}
You are creating dynamic data which requires you to use .on in jquery, otherwise it will not find the element.
Also dont repeat id's make it a class instead
$(document).on('click', '.addshipment', function () {
// in console, indexes closer to 0 (ex: index [0]) = newer
//$(".shipment:first").before(ADD_SHIPMENT_GRAY());
// add new shipment green block
$("#zzz").html(ADD_SHIPMENT_GRAY());
});
http://api.jquery.com/on/
I have two buttons. One where i clone a div (button-add) and one where I remove a div (button-remove).
I want to disable the remove-button when I only have one div.
So for multiple divs, it looks like this:
<button type="button" class="btn btn-default btn-lg button-add">+1</button>
<button type="button" class="btn btn-default btn-lg button-remove">-1</button>
<div class="copybox"></div>
<div class="copybox"></div>
<div class="copybox"></div>
...and when there's only one div, I want it to look like this:
<button type="button" class="btn btn-default btn-lg button-remove" disabled>-1</button>
<div class="copybox"></div>
I use jQuery 1.11.3
Here you go. Hope this is what you need.
$('.btn').on('click',function(){
if($(this).text()=="+1")
{
$('.button-remove').prop('disabled',false);
$('div.copybox:first').clone().appendTo('body');
}
else
{
$('div.copybox:last').remove();
}
$('div.copybox').length==1?$(this).prop('disabled',true):$(this).prop('disabled',false)
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<button type="button" class="btn btn-default btn-lg button-add">+1</button>
<button type="button" class="btn btn-default btn-lg button-remove">-1</button>
<div class="copybox">Copy</div>
<div class="copybox">Copy</div>
<div class="copybox">Copy</div>
Try using the $("div.copybox").length that DontVoteMeDown commented and then set an ID for the button remove. Once you do that, you can add a function to hide the button with this code.
document.getElementById(buttonID).style.display = 'none'
If later you decide to enable it again, then you can also add another if statement and then the code for that would be block instead of none
So I want to swap two div elements that have a CKEditor inside. I viewed some of the previous questions and tried to do it that way. It's all OK, the elements are swapped. But one of the elements loses its content and becomes non-editable.
<div id="sections">
<div id="apresentacao_div">
<label id="apresentacao_label" for="apresentacao">Apresentação</label>
<button class="btn btn-default">
<span class="glyphicon glyphicon-remove"></span>
</button>
<button class="btn btn-default">
<span class="glyphicon glyphicon-arrow-up"></span>
</button>
<CKEditor:CKEditorControl ID="apresentacao"></CKEditor:CKEditorControl>
</div>
<div id="intro_div">
<label id="intro_label" for="intro">Introdução</label>
<button class="btn btn-default" onclick="remove(this)">
<span class="glyphicon glyphicon-remove"></span>
</button>
<button class="btn btn-default" onclick="upDiv(this)">
<span class="glyphicon glyphicon-arrow-up"></span>
</button>
<CKEditor:CKEditorControl ID="intro"></CKEditor:CKEditorControl>
</div>
</div>
I want to swap the two divs within the div with the id = "sections". And this is my code to swap:
function upDiv(ex) {
var div = document.getElementById("sections").getElementsByTagName("div");
for (i = 0; i < div.length; i = i + 4) {
if (div[i + 4].id.localeCompare(ex.parentNode.id) == 0) {
swapElements(div[i + 4], div[i]);
return false;
}
}
return false;
}
function swapElements(obj1, obj2) {
obj2.nextSibling === obj1 ? obj1.parentNode.insertBefore(obj2, obj1.nextSibling) : obj1.parentNode.insertBefore(obj2, obj1);
}
The for loop increments by 4 because of the transformation of the textarea into CKEditor adds a lot of new divs (4 in this case).
Can anyone help?
Not having too much familiarity with exactly what you are doing but i would try using a 'clone' method and then removing the original element off the page. It may be the values are not being copied, only the outline is but a clone should mean it duplicates as it is on the page and not how it is from the page source.
What about just swapping the data instead? Moving the DOM elements around is causing problems to me as well, but this works:
Replace your upDiv with this:
function upDiv()
{
var introData = CKEDITOR.instances['intro'].getData();
var presentacaoData = CKEDITOR.instances['apresentacao'].getData();
CKEDITOR.instances['intro'].setData(presentacaoData);
CKEDITOR.instances['apresentacao'].setData(introData);
return false;
}
This takes the data from one, and puts it in the other and vice versa.
Also, I noticed your controls don't have the runat server attribute set. You may want to change this:
<CKEditor:CKEditorControl runat="server" ID="intro"></CKEditor:CKEditorControl>
Finally, you call the function from your button like this:
<button class="btn btn-default" onclick="return upDiv();">
<span class="glyphicon glyphicon-arrow-up"></span>
</button>