Selecting elements including nested children - javascript

I have a few rows with linked elements in them. The code looks like this:
<a href="link" class="list-group-item list-group-item-action" data-lat="30.25552298" data-lon="-97.555554">
<div class="row">
<div class="col-sm-12 col-md-7 col-lg-8 col-xl-9 lead">
label
</div>
<div class="col-sm-12 col-md-5 col-lg-4 col-xl-3 d-flex justify-content-between align-items-center">
<span class="badge bg-success"><small>33</small></span>
<strong>5 mi.</strong>
</div>
</div>
</a>
Then I use event listeners to call couple functions when my mouse moves over the links:
let loc = document.querySelectorAll("a[data-lat]");
var marker;
loc.forEach(node => {
node.addEventListener("mouseover", locOver);
node.addEventListener("mouseout", locOut);
})
function locOver(event) {
var llt = event.target.dataset["lat"],
lln = event.target.dataset["lon"];
marker = L.marker([llt, lln]).addTo(map);
}
function locOut(event) {
marker.remove();
}
Since there's a little padding on the link it works great when a mouse enters it, however, as soon as the mouse hits divs within the link the marker disappears, which seems weird to me since it's still linked.
I've tried modifying selector like this:
let loc = document.querySelectorAll("a[data-lat] div");
But my code just stops working, and no marker is shown. What am I missing here?

Related

Left align element with centered and variable width element in top row

I would like to find a way to left align <p> with centered <img> in the top.
As images are centered and my page contains different images with different widths, it seems to be a bit challenging.
Here is my html structure:
<div class="row">
<div class="container-fluid">
<div class="row">
<div class="col-md-4 my-auto">
<div class="d-flex flex-row justify-content-center">
<img class="img-fluid d-flex flex-wrap align-items-center" id="image-id">
</div>
</div>
<div class="col-md-8">
SOME CONTENT
</div>
</div>
<div class="collapse collapse-information">
<div class="row row-collapse m-0">
<!--What I want to be left aligned with img tag-->
</div>
</div>
</div>
</div>
A way to do it would be to get the distance between image's div and border of centered image and to report this measure as a left-margin on the element I want to be aligned.
To solve it, I tried to use margin measurments based on window width but it as not working.
While working to have a clean question, I went through https://developer.mozilla.org/en/docs/Web/API/HTMLElement/offsetLeft.
The interresting part is that, javascript allows a dynamic measurement I can also dynamically attribute to other elements.
// get left offset
var leftDistanceLogo = document.querySelector("#image-id").offsetLeft;
// assing as margin to the following element
document.querySelector('.row-collapse').style.marginLeft = leftDistanceLogo + "px";
Last interesting point, this code should wait until the end of page loading (otherwise offet will be equal to 0), so I called it in a structure like:
window.addEventListener("load", function (event) {
setTimeout(() => {
var leftDistanceLogo = document.querySelector("#image-id").offsetLeft;
document.querySelector('.row-collapse').style.marginLeft = leftDistanceLogo + "px";
}, 0);
});

Open Bootstrap modal clicking auto generated element

I've got a problem to open Bootstrap 4 modal using element generated by Javascript.
There are two very similar cards (identical but with diffrent id). First is hard coded in html doc (and work correctly). Another is generated by simple JS script. I try to use the same class name "openEditModal" but it doesn't work. Then I declared "data-toggle" "data-target" attributes for both but still work only hard coded card. Is there any possibility that Bootstrap JS file work only with hard coded element?
HTML Coded Card
<div class="row" id="all-contacts-box">
<!-- ____EXIST_ADDRESSES____ -->
<!-- addressBoxWrapper -->
<div class="col-xl-3 col-md-4 col-sm-6 col-12 mt-2 d-flex">
<!-- addressBox -->
<div class="card bg-light openEditModal label flex-fill">
<!--contactHeader-->
<div class="card-header pl-2 pt-1 font-weight-bold text-muted label-title">
Office Address
</div>
<!-- contactBody -->
<div class="card-body row pt-0">
<!-- contactBodyLeft -->
<div class="col-4 d-flex justify-content-center align-items-center maps-pin">
<i class="fas fa-map-marker-alt"></i>
</div>
<!-- contactBodyRight -->
<div class="col-8">
<h4 class="label-title font-weight-bold">Main Name</h4>
<h5 class="label-address font-weight-normal">Street 22</h5>
<h5 class="label-address font-weight-normal">City, Country</h5>
</div>
</div>
</div>
</div>
Part of JS Code that generate new card
var createContactBox = function(dataToDisplay, idCounter) {
var mainAddressContainer = document.getElementById("all-contacts-box");
var addNewBox = document.getElementById("add-new-box");
var addressBoxWrapper = document.createElement("div");
var addressBox = document.createElement("div");
mainAddressContainer.insertBefore(addressBoxWrapper, addNewBox);
addressBoxWrapper.appendChild(addressBox);
addressBoxWrapper.classList = "col-xl-3 col-md-4 col-sm-6 col-12 mt-2 d-
flex";
addressBox.classList = "card bg-light openEditModal label flex-fill";
addressBox.setAttribute("data-toggle", "modal");
addressBox.setAttribute("data-target", "editBoxModal");
};
$(".openEditModal").click(function() {
$("#editBoxModal").modal();
});
The problem with dynamically created elements, is that they aren’t born with the same event handlers as the existing elements.
In order to fix it, you need to "refresh" the listeners after you add a dynamically element.
So I add events handlers to a function and turn it off before I turn it on (something like restart). If you don't turn it off, the event will triggered as many times this function is called, and you don't want it.
function refreshEvents() {
$(".openEditModal").off();
$("#add-new-box").off();
$(".openEditModal").click(function() {
$("#editBoxModal").modal();
});
$("#add-new-box").click(function() {
$("#addNewBoxModal").modal();
});
}
Now you can call this function whenever you create another element.
So I call it after you created the element.
This is a working fiddle

Bootstrap Columns Toggle with Javascript

I need help with Bootstrap Columns Toggle that converts a 12 column grid into other two columns with 9 and 3 columns, and back to 12 columns again.
I have a prototype, but I can't seem to get it quite right. Here's the JSFIDDLE.
To understand the issue, I have 3 different scenarios that are explained in the prototype that basically starts at 12 columns, gets toggled to 9 + 3 columns, and back to 12 columns.
The HTML code is as follow:
<div class="container-fluid col-lg-12 col-md-12 col-sm-12 col-xs-12">
<h2 class="align-center">Current Prototype</h2></div>
<div id="LeftColumn" class="col-md-12 col-sm-12 col-xs-12">
<h4>Left Column</h4>
<p>Currently is set to col-md-9, but it should initially be col-md-12 and be toggled to col-md-9 while maintaining its responsive properties.</p>
<p><span class="strong">DESIRED RESULT:</span>Toggle the properties <div class="col-md-12 col-sm-12 col-xs-12"> to <div class="col-md-9 col-sm-9 col-xs-12"> when the "Toggle Right" column button is clicked while maintaining the existing functionality.</p>
<div id="Bar" class="main-container collapse in">
Toggle Right
</div>
<div class="clearfix"></div>
<br />
</div>
<div id="RightColumn" class="col-md-3 col-sm-3 col-xs-12">
<div id="Foo" class="main-container collapse" style="border: dotted 1px green;">
Toggle Left Column <i class="fa fa-bars"></i>Additional content will be displayed in this column once triggered.
<div style="height: 150px;"></div>
</div>
</div>
The Javascript that needs attention is as follow:
$(".main-container.collapse").on('shown.bs.collapse', function() {
//when a collapsed div is shown hide all other collapsible divs that are
visible
$(".main-container.collapse").not($(this)).collapse('hide');
});
$('#toggle-right').click(function(e) {
var left = $('#LeftColumn');
if (left.hasClass('col-md-9')) {
left.removeClass("col-md-9 col-sm-9").addClass("col-sm-12 col-md-12");
} else {
left.removeClass("col-md-12 col-sm-12").addClass("col-sm-9 col-md-9");
}
})
I would certainly appreciate any help and expertise you can provide with a custom jsfiddle. Thanks!
There are just couple of minor changes you need to do to toggle.
Problem: You are adding/removing the classes on the click of the #toggle-right button which is fine but you are NOT again doing the same on the next toggle button namely your <a>(yellow warning button) once your 12 columns get divided to 9 and 3.
<i class="fa fa-bars"></i>
Solution:
All you need to do is call that same function which adds/removes the classes on the click of the <a> button as well. Firstly give a class or an id to the element to identify it.
<i class="fa fa-bars"></i>
Now you just need to add that new selector in your existing click function.
$('#toggle-right, #toggle-left').click(function(e) {
var left = $('#LeftColumn');
if (left.hasClass('col-md-9')) {
left.removeClass("col-md-9 col-sm-9").addClass("col-sm-12 col-md-12");
} else {
left.removeClass("col-md-12 col-sm-12").addClass("col-sm-9 col-md-9");
}
})

AngularJS - JQuery News Ticker - After moving news the javascript function doesn't get called

This is an awkward problem, which will be better explained by looking at the live demo. Basically I have a news box populated with ng-repeat using Angular. Then I am using a jquery plugin called news ticker which allows the news headlines to move around. The first time you land on the page the news items are in their proper spots and they call the function accordingly. After moving them up or down, they stop calling the function, set a breakpoint in the code and after moving the breakpoint is never hit.
Edit - After researching this further I have found that it is because the elements need to be compiled using $compile after they're re added. However following some examples I have not gotten this to work. I need a way of compiling after a move event with this plugin.
Live demo
Angular Script for with function that should be called.
$scope.UpdateNews = function (item,number) {
console.log(item + ' ' + number);
switch (item)
{
case 'General':
$scope.NewsCast.General.Body = $scope.News.GeneralNews[number].Text;
break;
}
};
What the HTML looks like with the news boxes
<script src="http://www.jqueryscript.net/demo/Responsive-jQuery-News-Ticker-Plugin-with-Bootstrap-3-Bootstrap-News-Box/scripts/jquery.bootstrap.newsbox.min.js" type="text/javascript"></script>
<div class="row">
<div class="col-md-6 col-lg-3">
<div class="panel panel-default">
<div class="panel-heading"> <span class="glyphicon glyphicon-list-alt logo-inverse pull-left"></span><b> General News</b></div>
<div class="panel-body">
<div class="row">
<div class="col-xs-12">
<ul class="demo1" style="overflow-y: hidden; height: 280px;" ng-model="Idk">
<li style="" class="news-item text-left" ng-repeat="item in News.GeneralNews"><strong>{{item.DateValue | date: "MMM dd yyyy"}}</strong> {{item.Preview}}<a class="FakeClickable" ng-click="UpdateNews('General',item.index)" data-target="#GeneralModal" data-toggle="modal">Read more...</a></li>
</ul>
<div ng-if="Width>768">
<div ng-include="'../pages/Modals/General/GENERAL_INLINE.html'"></div>
</div>
</div>
</div>
</div>
<div class="panel-footer"> </div>
</div>
</div>

Swipe user media cards left/right to reveal next one

I am trying to implement a widget which ng-repeats user media objects horizontally and I should be able to swipe left/right to reveal the next media card. widget should look something like this
As you can see the image
The next card avatar is half visible, hinting there are more cards to swipe.
this is all i have currently.. i am stuck here
div class="media people-card-media col-xs-12" ng-repeat="item in cats">
<div class="media-left ">
<div class="person-photo presence" >
<img class="media-object list__photo img-circle" ng-src="{{item.photo}}" />
</div>
</div>
<div class="media-body list__body">
<div class="people_name_title">
<h4 class="media-heading title">{{item.name}}</h4>
</div>
</div>
<div class="media-right media-middle contacts-chat-call flex-it-align-top">
<a style="margin-right: 10px;">
call
</a>
</div>
</div>
heres the plunker http://plnkr.co/edit/YESgpGIXQrK9sYl79FVI?p=preview
Here is a plunkr with a working implementation.
http://plnkr.co/edit/wmIyCFM57hniZQ82Z8Ba?p=preview
I added ngTouch and in the HTML a ng-class and the touch event handlers.
<div class="media people-card-media col-xs-12"
ng-class="item.displayClass"
ng-repeat="item in heroes"
ng-click="gonext()"
ng-swipe-left="gonext()"
ng-swipe-right="goprev()">
And in the MainController, it flips through active item by assigning a current class to it, and a next-up and previous class to the neighbors.
$scope.gonext = function () {
for (var i=0, len=$scope.heroes.length; i<len; i++) {
if ($scope.heroes[i].displayClass == 'current') {
$scope.heroes[i].displayClass = 'previous';
if (i<len-1) $scope.heroes[i+1].displayClass = 'current';
if (i<len-2) $scope.heroes[i+2].displayClass = 'next-up';
i=len;
};
};
};
Only needs a better handling of the boundaries.

Categories