Jquery on-click; ajax, works but not exactly as intended - javascript

I thought of doing a fiddle for this, but since it's already online, and since I don't know fiddle that well, I figured it'd take me a long time to get it right on one. So...
The code's all there. And you can all see what the problem is...
The problem: I need it to remain that when one clicks the OIL, MILITARY, MISC tabs, the first rectangle border is red (as it is when you first scroll through them now). When one clicks the second, third, etc. rectangle on the oil tab, the border needs to be removed from the one that it currently is on and be applied to the one that was just clicked. Again, keeping the first rectangle on the MILITARY and MISC tabs as selected with a red border.
The code works, almost exactly as needed, but after spending a few hours trying to google and after rewriting the code several times (you can see some of my attempts commented out in the code), I cannot figure out what is wrong.
When you load the page, the TEST rectangle is selected. When you TEST 2 (or any other one) the red border is removed from TEST and applied to TEST 2 (or whichever one is clicked). When clicking any other, the red border remains and is added to the new one...but when TEST is reclicked (and gains the border again), and is then clicked out of (say, you click TEST 2 again), the border is removed once more...but it only works on TEST.
My question is thusly: what am I doing wrong? Why does it appear as though
var active_tab_selector2 = $('a[href='+active_div_data+']');
$(active_tab_selector2).parent('div').removeClass('selected');
is cached and not being re-ran on every click?
EDIT: (More code):
$("#lewy section div a").click(function(e) {
e.preventDefault();
var target_tab_selector2 = $(this).attr('href');
var active_div = $("#lewy div div.active a");
var active_div_data = $("#lewy div div.active a").data('default');
var active_tab_selector2 = $('a[href='+active_div_data+']');
$(active_tab_selector2).parent('div').removeClass('selected');
$(active_div).attr('data-default',target_tab_selector2);
var target = $('a[href='+target_tab_selector2+']');
$(target).parent('div').addClass('selected');
$.ajax({
type : "POST",
cache : false,
url : "mapStructureDisplay.php?s",
data : {'X': target_tab_selector2},
success: function(data) {
$("#secondary").html(data);
}
});
});
});
<div id="lewy" style="background-image:url('images/308.png');">
<div id="outer">
<div id="inner" class="active">OIL</div>
<div id="inner">MILITARY</div>
<div id="inner">MISC</div>
</div>
<section id="Div1" class="active">
<div id="structure" class="selected"><a class="button2" href="#str1">TEST</a></div>
<div id="structure"><a class="button2" href="#str2">TEST 2</a></div>
<div id="structure"><a class="button2" href="#str3">TEST 3</a></div>
<div id="structure"><a class="button2" href="#str4">TEST 4</a></div>
<div id="structure"><a class="button2" href="#str5">TEST 5</a></div>
<div id="structure"><a class="button2" href="#str6">TEST 6</a></div>
</section>
<section id="Div2" class="hide">
<div id="structure" class="selected"><a class="button2" href="#str7">TEST DIV 2</a></div>
</section>
<section id="Div3" class="hide">
<div id="structure" class="selected"><a class="button2" href="#str9">TEST DIV 3</a></div>
</section>
</div>
<div id="srodek">
</div>
<div id="prawy" style="background-image:url('images/246.png');">
<div id="secondary">TEST</div>
</div>
</div>

Try changing:
$(active_div).attr('data-default',target_tab_selector2);
to:
$(active_div).data('default',target_tab_selector2);
jQuery caches data-XXX attribute the first time you access them with .data(), and doesn't fetch them again. So modifying them with .attr() later won't be seen when you use .data('default') to read the attribute. You should be consistent, either use .attr for all setting and reading, or .data, but don't mix them.

Related

How to assert if an element is being visually displayed even if it exists in the DOM already?

I am using Capybara/Poltergeist with RSPEC for feature tests. :js => true is enabled as well.
After loading the page, when the page is ready, I want to interact with a menu bar that opens and closes via a click, with CSS animation, with content. Now, that content is already on the HTML page however it toggles a CSS class which has a display: none.
I do have this snippet to disable transitions in CSS only during tests.
- if Rails.env.development?
:javascript
var disableAnimationStyles = '-webkit-transition: none !important;' +
'-moz-transition: none !important;' +
'-ms-transition: none !important;' +
'-o-transition: none !important;' +
'transition: none !important;'
window.onload = function() {
var animationStyles = document.createElement('style');
animationStyles.type = 'text/css';
animationStyles.innerHTML = '* {' + disableAnimationStyles + '}';
document.head.appendChild(animationStyles);
};
Picture 1 (Opened):
Picture 2 (Opened):
My first step, I wait for the page to load and I click on the gray square as seen in the pictures and that gray box is supposed to open. So that is Picture 1. And my code passes however what I am looking for (Picture 2) is not displayed.
If I put a sleep(4) in before I take a screenshot, I am given the result of Picture 2 but my test passes. This is just a false positive since I just added a sleep there for my screenshot to take it and I assuming its the same assertion as my first example.
(The various commented out code are other things I have tried.)
At the end of the day, I would like to assert if "SILVER (BOXER BRIEFS)" is being successfully displayed visually. I am not sure if Poltergeist/Capybara is just checking to see if that text exists in the HTML source, which I don't want to check.
We were having an issue where the menu would not be displayed however that was because the CSS class "visible" was not being added, but even if I kept that code in the site, this test still passes regardless if the box is displayed or not.
Any suggestions on how to assert if that text is displayed, visually?
My current spec:
it "should open all available fabrics" do
find(:xpath, '//*[#id="sister-selector"]/div/div[3]/div').click
wait_for_ajax
expect(page).to have_css('.current-selection.sister-selector-mobile.disclosed')
expect(page).to have_css('.alternative-selections.sister-selector-mobile.visible')
take_screenshot
# expect(find("#sister-selector-mobile#{boxer_briefs_silver.id}").visible?).to be_falsey
# find(:css, "#sister-selector-mobile#{boxer_briefs_silver.id}").should be_visible
# expect(find("#sister-selector-mobile#{boxer_briefs_silver.id}", :visible => false)).to have_content(boxer_briefs_silver.name.upcase)
end
HTML:
<div class="current-selection sister-selector-mobile disclosed">
<div class="div" style="position: relative">
<i class="fa fa-chevron-down"></i>
<i class="fa fa-chevron-up"></i>
18 Hour Jersey
<br>
<span class="category">
(Boxer Briefs)
</span>
</div>
</div>
<div class="alternative-selections sister-selector-mobile visible">
<a href="#" data-navigate="product_detail" data-navigate-options="silver-boxer-brief">
<div class="selection">
<div class="the-line"></div>
<div>
<div class="heading" id="sister-selector-mobile51">
Silver
<br>
<span class="category">
(Boxer Briefs)
</span>
</div>
</div>
</div>
</a>
<a href="#" data-navigate="product_detail" data-navigate-options="3x3-boxer-briefs">
<div class="selection">
<div class="the-line"></div>
<div>
<div class="heading" id="sister-selector-mobile98">
3x3 Boxer Briefs
<br>
<span class="category">
(Boxer Briefs)
</span>
</div>
</div>
</div>
</a>
</div>
Assuming you haven't changed the Capybara defaults for visibility checks it should just be
expect(page).to have_content(boxer_briefs_silver.name.upcase)
or if you want to ensure its scoped to a part of the page, something like this (guessing from your selectors - posting actual html would make this easier)
#do your click here
menu_bar = find('#sister-selector')
expect(menu_bar).to have_text(boxer_briefs_silver.name.upcase)
Also, I see your test doesn't have js: true metadata, so I assume you have Capybara.default_driver set as :poltergeist - otherwise JS won't be supported and is needed for this test
What this test should really boil down to is
it "should open all available fabrics" do
menu_bar = find('#sister-selector')
menu_bar.find(:xpath, './/div/div[3]/div').click
expect(menu_bar).to have_text(boxer_briefs_silver.name.upcase)
end

JS pop-up for different items on page

I'm trying to make a pop-up for each item in my app to select quantity.
So it preloads several items on page, and I need to make it show pop-up when clicked on any of them.
I found this solution and tried it:
<div class="items">
<div class="menu_item_btn" href = "javascript:void(0)" onclick = "itemquantity()">
<%= item.name %>
</div>
<div id="light" class="itemshowcontent">
<p>Some content</p>
Close
</div>
<div id="fade" class="blackoverlay"></div>
</div>
where js:
<script>
function itemquantity() {
document.getElementById('light').style.display='block';
document.getElementById('fade').style.display='block'
}
function closeitemquantity() {
document.getElementById('light').style.display='none';
document.getElementById('fade').style.display='none'
}
</script>
It works, however when I select quantity, it always selects it only for the first item that comes.
If click on second item (or any other), the pop-up is still for the first one.
I believe this is because I use getElementById, as ID is used for only one object.
I tried changing to getElementsByClassName, but then it doesn't work at all. So, my question is how to make it work?
Should I stick to using classes? Or somehow use ID, within classes?
I apologise if it's simple question, I'm not really familiar with JS.
Any advice appreciated.
EDIT:
Here are some images for what I'm doing. This is page with listed objects:
These are the objects preloaded from DB shown in a list. When you click on any of them, this pop-up comes up:
to select quantity.
I'm developing in elixir and phoenix framework.
Give id to each item and move light and fade out from id and to class. Then, find light and fade by item id when click function is executed. See the following example.
function getParent(itemChild) { // Get parent.
var item = itemChild.parentElement;
return item;
}
function itemquantity(itemChild) {
var item = getParent(itemChild); // Get parent and it is the item.
item.querySelector('.light').style.display='block'; // Find .light element as of item.
item.querySelector('.fade').style.display='block'; // Find .fade element as of item.
}
function closeitemquantity(itemChild) {
var item = getParent(getParent(itemChild)); // You have to get parent twice and that is the item.
item.querySelector('.light').style.display='none'; // Find .light element as of item.
item.querySelector('.fade').style.display='none'; // Find .fade element as of item.
}
<div class="items" id="apple">
<div class="menu_item_btn" href = "javascript:void(0)" onclick = "itemquantity(this)">
Apple
</div>
<div class="light itemshowcontent">
<p>Red Apple</p>
Close
</div>
<div class="fade blackoverlay"></div>
</div>
<div class="items" id="banana">
<div class="menu_item_btn" href = "javascript:void(0)" onclick = "itemquantity(this)">
Banana
</div>
<div class="light itemshowcontent">
<p>Yello Banana</p>
Close
</div>
<div class="fade blackoverlay"></div>
</div>

Unwanted highlighting selection of HTML element

I am making a website (just for fun) where you can play the game SET. Now an intermittent problem has cropped up which I do not understand.
The user selects squares by clicking on them (the board is made up of floated DIV elements with images inside of them). When clicked, the border of the DIV becomes yellow.
The unwanted behavior that is happening here is that when a user clicks on the first DIV to highlight it, another div becomes highlighted (see below). The worst part is that the problem happens only intermittently, maybe once out of every five times a user begins selecting a set. I am not sure what code to post as I really cannot guess what is the source of the error.
Here is the code that makes squares light up, although I am not at all sure that the error is in this code:
var myDown = isIOS ? "touchstart" : "mousedown";
$(".cell").on(myDown,function(event) {
if (declared == true) {
if ($(this).hasClass('on')) {
$(this).removeClass('on');
} else {
if ($('.cell.on').length <3) {
$(this).addClass('on');
}
}
if ($('.cell.on').length == 3) {
$submitButton.addClass('ready');
setTimeout(delayedSubmit,400);
}
}
});
Here is a screenshot of the problem:
The square that is highlighted in blue should not be highlighted at all. I clicked on the square in the third column, second row, and that square does have a yellow border to indicate that it was clicked.
In the end I guess I'm just hoping someone else will have had a similar experience with weird, unwanted DIV highlighting so as to suggest a possible cause.
EDIT: Here is a bit of the HTML
<div id="board" class="">
<div id="A1" class="cell">
<div class="box">
<a class="stretchy no-limit" href="#"><img class="spacer" src="/img/spacer.png" alt="spacer"><img class="sprite one empty" id="c0012" alt="card" src="/img/12.png"></a>
</div>
</div>
<div id="B1" class="cell">
<div class="box">
<a class="stretchy no-limit" href="#"><img class="spacer" src="/img/spacer.png" alt="spacer"><img class="sprite three empty" id="c2001" alt="card" src="/img/01.png"></a>
</div>
</div>
<div id="C1" class="cell">
<div class="box">
<a class="stretchy no-limit" href="#"><img class="spacer" src="/img/spacer.png" alt="spacer"><img class="sprite one solid" id="c0202" alt="card" src="/img/02.png"></a>
</div>
</div>
etc.
If I understand the problem you can solve this issue by
Add a css property user-select:none
Add -webkit-tap-highlight-color: rgba(0,0,0,0); to the relevant tag.

jQuery UI sortable div's, how to determine the order in place?

Well I have three blocks that I want for the user to be able to sort as he pleased :
<div id="sortable" class="row ui-sortable">
<div class="boxEncar">
<div class="col-md-4 ui-sortable">
<div id="8_5_middle1" class="block block-8">
<div id="editor-container">
<h2 id="title8">Block 8</h2>
<p>Well, the way they make shows is, they make one show. That show's called a pilot. Then they show that show to the people who make shows, and on the strength of that one show they decide if they're going to make more shows. Some pilots get picked and become television programs. Some don't, become nothing. She starred in one of the ones that became nothing.</p>
</div>
</div>
</div>
<div class="col-md-4 ui-sortable">
<div id="7_6_middle2" class="block block-7">
<div id="editor-container">
<h2 id="title7">Block 7</h2>
<p>Do you see any Teletubbies in here? Do you see a slender plastic tag clipped to my shirt with my name printed on it? Do you see a little Asian child with a blank expression on his face sitting outside on a mechanical helicopter that shakes when you put quarters in it? No? Well, that's what you see at a toy store. And you must think you're in a toy store, because you're here shopping for an infant named Jeb.</p>
</div>
</div>
</div>
<div class="col-md-4 ui-sortable">
<div id="9_7_middle3" class="block block-9">
<div id="editor-container">
<h2 id="title9">Block 9</h2>
<p>Your bones don't break, mine do. That's clear. Your cells react to bacteria and viruses differently than mine. You don't get sick, I do. That's also clear. But for some reason, you and I react the exact same way to water. We swallow it too fast, we choke. We get some in our lungs, we drown. However unreal it may seem, we are connected, you and I. We're on the same curve, just on opposite ends.</p>
</div>
</div>
</div>
</div>
</div>
The id 8_5_middle1 for example, show's weight _ block-id _ zone that are stocked on the database like this :
ZONE | bid | weight
---------------------------
middle1 | 8 | 5
---------------------------
middle2 | 7 | 6
---------------------------
middle3 | 9 | 7
So the issue here is this:
jQuery(document).ready(function() {
jQuery('.col-md-4').sortable({
connectWith: ".col-md-4",
items: ".block",
update: function (event, ui) {
var myTable = jQuery(this).sortable('toArray').toString();
alert(myTable);
}
});
});
When I drag a block to another "let's say that I drag the block8 from middle1 to middle2 " here's my alert : 8_5_middle1,7_6_middle2 meaning that it just alert the old position! Is there a way to alert the new zone which the block is positionned ? Much appreciated
Is this what you want?
jQuery('.col-md-4').sortable({
connectWith: ".col-md-4",
items: ".block",
update: function (event, ui) {
var myTable = jQuery(this).sortable('toArray').toString();
//alert(myTable);
alert($(ui.item).index());
}
});
$(ui.item).index(); will return the current item index, the element ids are not changing so how would you get an updated zone?
Edit:
If you want to get the dragged item id or other attributes, you may use $(ui.item).attr('id')
fiddle link
Since you are passing the ui object, there are several things you have available there. It will be very helpful to understand if you console.log(ui) and examine the object contents.

Javascript on Multiple DIVs

I am using a Wordpress Theme (Incipiens) that has a show/hide Javascript to show a map on the contact page http://demo.themedev.me/wordpress_themes/incipiens/contact-us/
I want to use this function on a page multiple times to show/hide galleries.
<div class="map">
<div class="map_top">
<hr class="toolbox toolbox1">
</div>
<hr class="vertical_sep0">
<a class="show_map" href="javascript:void(0)"></a>
<div class="map_container"><div class="thismap"><iframe>........</iframe></div>
</div>
I have this working but the call to the js opens all divs. I therefore put a unique div id round each gallery and slightly changed the javscript...
<div class="map">
<div class="map_top">
<hr class="toolbox toolbox1">
</div>
<hr class="vertical_sep0">
<div id="silestone">
<div class="map_container">
[show_gallery width="124" height="124" galleryid="527"][/show_gallery]
</div>
</div>
</div>
It works but very oddly, sometimes the right one opens, sometimes the wrong one...not sure what i'm doing wrong, should I just have one javascript call that contains the ID's to all divs? If so how do I do this?
Since you have not shown the actual script you use for toggling, I assume you mean something like this (taken from the page) -
function (){
$(this).toggleClass('hide_map');
$('.map_container').slideToggle(400);
}
I would change that to -
function unhide(id){
$(this).toggleClass('hide_map');
$('#' + id).find('.map_container').slideToggle(400);
}
Does that work?

Categories

Resources