Update data value via jquery - javascript

I need to update two data value.
When I click on a div with class .messageconv grab the data-unread_mess_n value and subtract it from data-menutop_mess_nr and by the same data-unread_mess_n.
If the value of data-menutop_mess_nr==0 change the class.I can't update data-unread_mess_n and data-menutop_mess values why?
$(document).on('click touchstart', '.messageconv', function(e) {
e.preventDefault();
messagesNumber($(this));
});
function messagesNumber(elem) {
var numMess = elem.parent().data('unread_mess_n');
var numMessMenutop = $('#menutop_mess_nr').data('menutop_mess_nr');
if (numMess != 0) {
elem.children('p').remove();
}
var remainingMess = numMessMenutop - numMess;
$('#menutop_mess_nr').html(remainingMess);
if (remainingMess == 0) {
$('#menutop_mess_nr').addClass('bluecount').removeClass('redcount');
}
elem.parent().data('unread_mess_n','0');
$('#menutop_mess_nr').data('menutop_mess_nr',remainingMess);
}
.messageconv{
border: 2px solid red;
height: 50px;
}
.redcount {
background: #de2424;
width:30px;
}
.bluecount {
background: #333399;
width:30px;
}
.redcount:hover {
background: #ed4747;
text-decoration: none;
}
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<a data-unread_mess_n="2" href="5">
<div class="messageconv">
test
<p class="incmessage redcount">2</p></div>
</a>
<a data-unread_mess_n="3" href="4">
<div class="messageconv">
test1
<p class="incmessage redcount">3</p></div>
</a>
<p data-menutop_mess_nr="5" id="menutop_mess_nr" class="incmessage redcount">5</p>

You can try this
elem.parent().attr('unread_mess_n','0');

Related

Giving a div a style on click

applying a class to an element only when clicked
You could make 2 different click functions. One for trap and one for the rest.
For that you need to know which ones are the other ( safe ones ). See otherDivsIds in the below code. You find the other id's using the filter function in the idArray and then loop through them ( with forEach or something else ) and add event listeners to each of them.
I would also suggest to ' swap ' the naming of the variables trapBox and trapId. Vice versa would be better
See code below
var idArray = ['one','two','three','four'];
var trapBox = idArray[Math.floor(Math.random() * idArray.length)];
var trapId= document.getElementById(trapBox);
trapId.addEventListener('click', boomClickFunction, false);
var otherDivsIds = idArray.filter(id => id !== trapBox);
otherDivsIds.forEach(id => {
safeBox = document.getElementById(id);
safeBox.addEventListener('click', safeClickFunction, false)
})
var timeoutId = window.setTimeout(ticker, 5000);
function ticker() {
document.getElementById('timesUp').innerHTML = "Time's up!";
document.body.style.backgroundColor = "black";
}
function boomClickFunction() {
this.classList.add('boom')
}
function safeClickFunction() {
this.classList.add('safe')
}
div {
width: 20px;
height: 20px;
background-color: green;
margin: 20px;
float: left;
}
.boom {
background-color: red;
}
.safe {
background-color: lightblue;
}
#timesUp {
color: white;
}
<div id='one'>
</div>
<div id='two'>
</div>
<div id='three'>
</div>
<div id='four'>
</div>
<span id="timesUp">
</span>
You can add a class to an element by using classList.add('classToBeAdded').
In your case, you could put it in your clickFunction:
trapId.classList.add('boom');

Why is my text output from next() and prev() toggle incorrect?

When clicking the arrows to change the displayed option, the incorrect options is shown.
The user should be able click on the option menu to toggle it open/cosed and be able to click on a option to select it. Alternatively, the arrows could be used to toggle through the options instead.
This is the problematic code:
<script>
$("#arrow_left_physics").click(function() {
var $selected = $(".left_menu_option_selected").removeClass("left_menu_option_selected");
var divs = $("#left_menu__variant_physics").children();
divs.eq((divs.index($selected) - 1) % divs.length).addClass("left_menu_option_selected");
$("#left_menu_open .button-text").text($($selected).text());
});
$("#arrow_right_physics").click(function() {
var $selected = $(".left_menu_option_selected").removeClass("left_menu_option_selected");
var divs = $selected.parent().children();
divs.eq((divs.index($selected) + 1) % divs.length).addClass("left_menu_option_selected");
$("#left_menu_open .button-text").text($($selected).text());
});
</script>
$("#menu_open").click(function() {
$("#menu").toggle();
});
$(".menu_option").click(function() {
if ($(this).hasClass(".menu_option_selected")) {} else {
$(".menu_option").removeClass("menu_option_selected");
$(this).addClass("menu_option_selected");
$("#menu_open .button_text").text($(this).text());
}
});
$("#arrow_left").click(function() {
var $selected = $(".menu_option_selected").removeClass("menu_option_selected");
var options = $("#menu").children();
options.eq((options.index($selected) - 1) % options.length).addClass("menu_option_selected");
$("#menu_open .button_text").text($($selected).text());
});
$("#arrow_right").click(function() {
var $selected = $(".menu_option_selected").removeClass("menu_option_selected");
var options = $("#menu").children();
options.eq((options.index($selected) + 1) % options.length).addClass("menu_option_selected");
$("#menu_open .button_text").text($($selected).text());
});
.menu_open {
Cursor: pointer;
}
.menu {
display: none;
position: absolute;
border: 1px solid;
}
.menu_option {
Cursor: pointer;
Padding: 5px;
}
.menu_option:hover {
Background-Color: black;
Color: white;
}
.menu_option_selected {
color: green;
Background-color: #00ff0a4d;
}
.menu_option_selected:hover {
color: green;
}
.arrow {
Cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<input class="arrow" type="button" id="arrow_left" value="❮" />
<input class="arrow" type="button" id="arrow_right" value="❯" />
</div>
<div>
<button class="menu_open" id="menu_open">
<span class="button_text">option1</span>
</button>
</div>
<div class="menu" id=menu>
<div class="menu_option menu_option_selected">option1</div>
<div class="menu_option">option2</div>
<div class="menu_option">option3</div>
<div class="menu_option">option4</div>
<div class="menu_option">option5</div>
<div class="menu_option">option6</div>
</div>
-It seems that the first click of the arrows isn't working and that the index function is incorrect somewhere.
The problem is this line:
$("#menu_open .button_text").text($($selected).text());
$($selected) is the option that was previously selected, so you're showing the text of the previous option, not the current option. (BTW, there's no need to wrap $selected in $(), since it's already a jQuery object.)
You should use $(".menu_option_selected").text() instead of $($selected).text() to get the current option.
You should also make the initial text of the button option1, so it matches the selected option.
$("#menu_open").click(function() {
$("#menu").toggle();
});
$(".menu_option").click(function() {
if ($(this).hasClass(".menu_option_selected")) {} else {
$(".menu_option").removeClass("menu_option_selected");
$(this).addClass("menu_option_selected");
$("#menu_open .button_text").text($(this).text());
}
});
$("#arrow_left").click(function() {
var $selected = $(".menu_option_selected").removeClass("menu_option_selected");
var options = $("#menu").children();
options.eq((options.index($selected) - 1) % options.length).addClass("menu_option_selected");
$("#menu_open .button_text").text($(".menu_option_selected").text());
});
$("#arrow_right").click(function() {
var $selected = $(".menu_option_selected").removeClass("menu_option_selected");
var options = $("#menu").children();
options.eq((options.index($selected) + 1) % options.length).addClass("menu_option_selected");
$("#menu_open .button_text").text($(".menu_option_selected").text());
});
.menu_open {
Cursor: pointer;
}
.menu {
display: none;
position: absolute;
border: 1px solid;
}
.menu_option {
Cursor: pointer;
Padding: 5px;
}
.menu_option:hover {
Background-Color: black;
Color: white;
}
.menu_option_selected {
color: green;
Background-color: #00ff0a4d;
}
.menu_option_selected:hover {
color: green;
}
.arrow {
Cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<input class="arrow" type="button" id="arrow_left" value="❮" />
<input class="arrow" type="button" id="arrow_right" value="❯" />
</div>
<div>
<button class="menu_open" id="menu_open">
<span class="button_text">option1</span>
</button>
</div>
<div class="menu" id=menu>
<div class="menu_option menu_option_selected">option1</div>
<div class="menu_option">option2</div>
<div class="menu_option">option3</div>
<div class="menu_option">option4</div>
<div class="menu_option">option5</div>
<div class="menu_option">option6</div>
</div>
Just another version, refactoring your javascript code with some Arrow functions.
const setButtonText = () => {
$("#menu_open .button_text").text(
$(".menu_option_selected").text()
);
}
const moveSelection = direction => {
var selected = $(".menu_option_selected")
var options = $("#menu").children()
var newIndex;
if (direction == 'right') {
newIndex = (options.index(selected) + 1) % options.length
} else {
newIndex = (options.index(selected) - 1) % options.length
}
selected.removeClass("menu_option_selected")
options.eq(newIndex).addClass("menu_option_selected")
setButtonText()
}
// inizilize menu button_text
setButtonText()
$("#arrow_left").click(() => moveSelection('left'));
$("#arrow_right").click( () => moveSelection('right'));
$("#menu_open").click( () => $("#menu").toggle());
$(".menu_option").click( function() {
$(".menu_option_selected").removeClass("menu_option_selected")
$(this).addClass("menu_option_selected")
setButtonText()
});

Add a div below inline-block wrapped row - Part 2

A solution suggested by #musicnothing in an older thread displays a content div below the row of inline divs, this works good when the div.wrapblock is clicked itself.
http://jsfiddle.net/SYJaj/7/
function placeAfter($block) {
$block.after($('#content'));
}
$('.wrapblock').click(function() {
$('#content').css('display','inline-block');
var top = $(this).offset().top;
var $blocks = $(this).nextAll('.wrapblock');
if ($blocks.length == 0) {
placeAfter($(this));
return false;
}
$blocks.each(function(i, j) {
if($(this).offset().top != top) {
placeAfter($(this).prev('.wrapblock'));
return false;
} else if ((i + 1) == $blocks.length) {
placeAfter($(this));
return false;
}
});
});
The issue I'm having.
I need to trigger the same effect, but by adding the click event to a link within the wrapblock itself.
My code is nearly identical.
What I have changed is the click event handle, from $('.wrapblock').click(function() to $('.more').on('click', function() I also needed to add .closest(".wrapblock") for the content div to position itself outside of the wrapblock.
$('.more').on('click', function() {
...
if ($blocks.length == 0) {
placeAfter($(this).closest(".wrapblock"));
return false;
}
Everything can be seen and tested http://jsfiddle.net/7Lt1hnaL/
Would be great if somebody could shed some light on how I can calculate which block it needs to follow with the offset method, thanks in advance.
As you can see in the latest fiddle example, the content div is not displaying below the row of divs.
I also apologise, I wanted to post on the thread in discussion but I only have a minor posting reputation which doesn't let me, thanks.
var $chosen = null;
var $allBlocks = [];
$(function(){
$allBlocks = $('.wrapblock');
})
$(window).on('resize', function() {
if ($chosen != null) {
$('#content').css('display','none');
$('body').append($('#content'));
$chosen.trigger('click');
}
});
$('.more').on('click', function() {
$chosen = $(this);
var position = $chosen.parent('.wrapblock').position();
$('#content').css('display','inline-block');
$allBlocks.filter(function(idx, ele){
return $(ele).position().top == position.top;
})
.last()
.after($('#content'));
});
.wrapblock
{
background: #963a3a;
display: inline-block;
width: 90px;
height: 90px;
color: white;
font-size: 14px;
text-align: left;
padding: 10px;
margin: 10px;
vertical-align:top;
position:relative;
}
#content
{
display:none;
vertical-align:top;
width:100%;
background: #5582c1;
font-size: 12px;
color: white;
padding: 10px;
}
.more {
position:absolute;
bottom:15px;
right:15px;
cursor:pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<div class="wrapblock">1
<span class="more" data-ref="1">more</span>
</div>
<div class="wrapblock">2
<span class="more" data-ref="2">more</span>
</div>
<div class="wrapblock">3
<span class="more" data-ref="3">more</span>
</div>
<div class="wrapblock">4
<span class="more" data-ref="4">more</span>
</div>
<div class="wrapblock">5
<span class="more" data-ref="5">more</span>
</div>
<div class="wrapblock">6
<span class="more" data-ref="6">more</span>
</div>
<div class="wrapblock">7
<span class="more" data-ref="7">more</span>
</div>
<div class="wrapblock">8
<span class="more" data-ref="8">more</span>
</div>
<div class="wrapblock">9
<span class="more" data-ref="9">more</span>
</div>
<div id="content">Some Content</div>
Seems to do what you want. Basically, it just filters down the set of all blocks to the row of the block you clicked on using the assumption that they'll all have the same vertical offset (top), then takes the last one, because jQuery will keep them in document order, so that'll be the last one in the layout row.
Oh, and I updated the fiddle http://jsfiddle.net/7Lt1hnaL/1/

Changing - css - backgroundColor function (pure javascript) doesn't work

Could anyone tell me why changing colour after performing onclick doesn't work here ?
function butt(color) {
if(document.getElementById("bt").style.backgroundColor=="green"){
document.getElementById("bt").style.backgroundColor="purple";
}
};
document.getElementById("bt").addEventListener("click", function() {
butt("green")
});
#bt {
background-color:yellow;
border-radius:10%;
padding:10px;
margin:20px;
}
<div class="row">
<div id="forbutton">
<button type="button" id="bt">It's me MrButton !</button>
</div>
</div>
You are just passing the string "green" through the function. Details commented in Snippet.
SNIPPET
// pass the string through function
function butt(color) {
// If string is "green"...
if (color === "green") {
// Reference #bt and change it's backgroundColor to purple
document.getElementById("bt").style.backgroundColor = "purple";
}
};
// Register #bt to click event, when clicked...
document.getElementById("bt").addEventListener("click", function() {
// Call butt() function passing the string "green"
butt("green")
});
#bt {
background-color: yellow;
border-radius: 10%;
padding: 10px;
margin: 20px;
}
<div class="row">
<div id="forbutton">
<button id="bt">It's me MrButton !</button>
</div>

Filter through elements with same class but not in the same wrapper

Using the method I found here I'm trying to upgrade the functionality of my previous question.
Basically I want to cycle through my elements with previous and next buttons. I cannot use nextAll() and prevAll() functions because they are not all in the same wrapper, so I used the most upvoted solution from the first link. Next cycling works fine, and previous doesn't.
var $content = $(".big_container");
var $loaded_content = $(".details");
var $item_selector = $(".item");
var $previous = $('.previous');
var $next = $('.next');
if ($content.length > 0) {
$item_selector.on('click', function(e) {
e.preventDefault();
var $this = $(this);
load_gallery_container($this);
});
$next.on('click', function(e) {
e.preventDefault();
var $next_item = $content.find('.current').findNext('.item');
if ($content.find('.item').hasClass('current')) {
if ($next_item.length) {
$content.find('.item').removeClass('current');
}
load_gallery_container_next_prev($next_item);
}
});
$previous.on('click', function(e) {
e.preventDefault();
var $prev_item = $content.find('.current').findPrev('.item');
if ($content.find('.item').hasClass('current')) {
if ($prev_item.length) {
$content.find('.item').removeClass('current');
}
load_gallery_container_next_prev($prev_item);
}
});
}
//Next all items
$.fn.findNextAll = function(selector) {
var that = this[0],
selection = $(selector).get();
return this.pushStack(!that && selection || $.grep(selection, function(n) {
return that.compareDocumentPosition(n) & (1 << 2);
// if you are looking for previous elements it should be & (1<<1);
}));
}
$.fn.findNext = function(selector) {
return this.pushStack(this.findNextAll(selector).first());
}
//Previous all items
$.fn.findPreviousAll = function(selector) {
var that = this[0],
selection = $(selector).get();
return this.pushStack(!that && selection || $.grep(selection, function(n) {
return that.compareDocumentPosition(n) & (1 << 1);
// if you are looking for previous elements it should be & (1<<1);
}).reverse());
}
$.fn.findPrev = function(selector) {
return this.pushStack(this.findPreviousAll(selector).first());
}
function load_gallery_container_next_prev($container) {
$loaded_content.find('.div_content').html($container.data('content'));
$container.addClass('current');
}
function load_gallery_container($container) {
if ($container.hasClass("current")) {
$loaded_content.slideUp('slow', function() {
$(this).removeClass('open');
$container.removeClass("current");
});
} else {
var $insert_after = $container.parent('.wrappers'),
$current = $('.current');
$current.removeClass('current');
if ($current.parent('.wrappers').is($insert_after)) {
$loaded_content.find('.div_content').html($container.data('content'));
$container.addClass("current");
} else {
if ($loaded_content.hasClass("open")) {
$loaded_content.slideUp('slow', function() {
$(this).removeClass('open');
$container.removeClass("current");
$loaded_content.detach().insertAfter($insert_after);
$loaded_content.find('.div_content').html($container.data('content'));
});
} else {
$loaded_content.detach().insertAfter($insert_after);
$loaded_content.find('.div_content').html($container.data('content'));
}
$loaded_content.slideDown('slow', function() {
$container.addClass("current");
$(this).addClass('open');
});
}
}
setTimeout(function() {
$('html, body').animate({
scrollTop: $loaded_content.offset().top - 300
}, 500);
}, 600);
}
.big_container {
background: #141414;
display: block;
padding: 30px;
}
.wrappers {
width: 500px;
margin: 0 auto;
display: block;
}
.item {
width: 31%;
height: 100px;
margin-right: 1%;
margin-bottom: 30px;
text-align: center;
background: #ccc;
color: #fff;
display: inline-block;
}
.details {
background: #ddd;
width: 100%;
padding: 30px;
display: none;
}
.navigation {
display: block;
text-align: center;
color: #fff;
}
.previous,
.next {
font-size: 18px;
display: inline-block;
margin: 0 12px 10px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="big_container">
<div class="navigation">
<div class="previous">
<</div>
<div class="next">></div>
</div>
<div class="wrappers">
<div class="item" data-content="blabla bla bla blaaaa">Click on meee!</div>
<div class="item" data-content="blabla BLALALA bla blaaaa">Click on meee!</div>
<div class="item" data-content="blabla blBLALbla blaaaa">Click on meee!</div>
</div>
<div class="wrappers">
<div class="item" data-content="blabla bla bla randomness">Click on meee!</div>
<div class="item" data-content="blabla bla bla ">Click on meee!</div>
<div class="item" data-content="blabla bla bla weeee">Click on meee!</div>
</div>
<div class="wrappers">
<div class="item" data-content="blabla bla bla blaaaa">Click on meee!</div>
<div class="item" data-content="blabla bla bla???">Click on meee!</div>
<div class="item" data-content="I am done with blaaaaing">Click on meee!</div>
</div>
<div class="details">The content from div goes here:
<div class="div_content"></div>
</div>
</div>
Basically when I click previous I get sent back to first element in the list, and not to the previous one. So the findPrev() function needs modifying, and I tried a lot: changing .first() to .last() and .prev() and even .prevAll(); tried changing return that.compareDocumentPosition(n) & (1<<1);
Nothing changed that would make this go to previous item. Anybody has an idea what is wrong with it?
ANSWER
Ok, so the solution is this:
$.fn.findPreviousAll = function( selector ){
var that = this[ 0 ],
selection = $( selector ).get();
return this.pushStack(
!that && selection || $.grep( selection, function(n){
return that.compareDocumentPosition(n) & (1<<1);
// if you are looking for previous elements it should be & (1<<1);
}).reverse()
);
};
$.fn.findPrev = function( selector ){
return this.pushStack( this.findPreviousAll( selector ).first() );
};
What the findPreviousAll function was doing was returning an array from first element to the one I clicked on, so I just needed to reverse it! And a simple .reverse() did it :)
I updated the snippet so it works! :)
Change this:
var $prev_item = $content.find('.current').findPrev('.item');
if ($content.find('.item').hasClass('current')) {
if ($prev_item.length) {
$content.find('.item').removeClass('current');
}
load_gallery_container_next_prev($prev_item);
}
to this:
var $prev_item = $(".item")[$(".item").index($(".item.current"))-1];
if($prev_item){
$(".item.current").removeClass('current');
}
$($prev_item).addClass('current');
load_gallery_container_next_prev($prev_item);
and change this:
function load_gallery_container_next_prev($container) {
$loaded_content.find('.div_content').html($container.data('content'));
$container.addClass('current');
}
to this:
function load_gallery_container_next_prev($container) {
$loaded_content.find('.div_content').html($($container).attr("data-content"));
$container.addClass('current');
}
Here is the JSFiddle demo :)

Categories