push replaces the old value in the array - javascript

Maybe its because I have been working all day and I can't see the problem. But in the following code the alert only shows the last added value and doesn't push the value in the array. :(
window.sortControl = {
sortControlPanel: $('div.sortControl'),
simpleSortCriteriaList: $('div.sortControl .simple'),
advancedSortCriteriaList: $('div.sortControl .advanced'),
dropDownExpander: $('div.sortControl .dropDownExpand.primary'),
dropDownContent: $('div.sortControl .dropdownContent.primary'),
simpleSortCriteria: $('div.sortControl .sortcriteria.simple a'),
simpleSortCheckboxes: $('.simple .checkbox'),
openAdvancedButton: $('.openAdvanced'),
backtoSimpleButton: $('.backtoSimple'),
advancedDropdownContent: $('div.sortControl .advanced .dropdownContent'),
advancedDropdownExpander: $('div.sortControl .advanced .dropDownExpand')
};
$.each(sortControl.advancedDropdownContent.parent(), function () {
var dropdownContent = $(this).find('.dropdownContent');
var input = $(this).find('input');
$(this).find('.dropDownExpand').live('click', function (event) {
sortControl.advancedDropdownContent.not(dropdownContent).hide('fast');
dropdownContent.toggle('fast');
event.preventDefault();
});
var currentSelectedGroups = [];
$(this).find('li a').bind('click', function (event) {
var criteria = $(this).text();
//if (!currentSelectedGroups.inArray($(this).attr('class'), true)) {
input.attr('value', criteria);
currentSelectedGroups.push($(this).attr('class'));
//}
dropdownContent.toggle('fast');
event.preventDefault();
alert(currentSelectedGroups);
});
});
Some of the html:
<div class='sortcriteria advanced'>
<label>Sort by: </label>
<div class='controlWrapper'>
<input type="text" placeholder='Any' value='Any' class='dropDownExpand'>
<span class='icon dropDownExpand' title='Select property type'></span>
<ul class='dropdownContent'>
<li><a href='#' class='price'>Price ascending</a></li>
<li><a href='#' class='price'>Price descending</a></li>
<li><a href='#' class='party'>Party size ascending</a></li>
<li><a href='#' class='party'>Party size descending</a></li>
<li><a href='#' class='bedrooms'>Number of bedrooms ascending</a></li>
<li><a href='#' class='bedrooms'>Number of bedrooms descending</a></li>
<li><a href='#' class='star'>Star rating ascending</a></li>
<li><a href='#' class='star'>Star rating descending</a></li>
</ul>
</div> ...
There are no JavaScript errors.
Content and this script get loaded via ajax
All other statements do what they are supposed to

You need to move var currentSelectedGroups = []; outside the each loop. You declare it once for every instance - they all work on their own version of the variable because it lives in the local scope of the each function.
Remember in javascript functions = scope

As I asked you (and suspected) in my earlier comment, you need to move:
var currentSelectedGroups = [];
outside the .each() loop. As it is you are re-initializing it to an empty array in each iteration of the loop so it never has more than one value in it. You can do that like this:
var currentSelectedGroups = [];
$.each(sortControl.advancedDropdownContent.parent(), function () {
var dropdownContent = $(this).find('.dropdownContent');
var input = $(this).find('input');
$(this).find('.dropDownExpand').live('click', function (event) {
sortControl.advancedDropdownContent.not(dropdownContent).hide('fast');
dropdownContent.toggle('fast');
event.preventDefault();
});
$(this).find('li a').bind('click', function (event) {
var criteria = $(this).text();
//if (!currentSelectedGroups.inArray($(this).attr('class'), true)) {
input.attr('value', criteria);
currentSelectedGroups.push($(this).attr('class'));
//}
dropdownContent.toggle('fast');
event.preventDefault();
alert(currentSelectedGroups);
});
});

Related

How to make links added from JSON clickable?

I am trying to append links from a JSON file but their onClick is not working.
HTML:
<li class="nav-item dropdown" id = "views">
<a class="nav-link dropdown-toggle" id="view-type" data-toggle="dropdown" data-selected="high_level" aria-haspopup="true" aria-expanded="false">High Level View</a>
<div class="dropdown-menu" aria-labelledby="view-type" style="height: 35vh; overflow: auto;">
<h7 class="dropdown-header">View Type</h7>
<a class="dropdown-item filter-option active" href="javascript:void(0);" id="high_level">High Level View</a>
</div>
</li>
Javascript:
d3.json(theURL, function(error, data) {
if (error) throw error;
var unique = [];
data.forEach(function(e){
if(unique.indexOf(e.segment) == -1){
unique.push(e.segment);
}
});
unique.forEach(d =>
$('#views .dropdown-menu').append(`<a class="dropdown-item filter-option ecodes" href="javascript:void(0);" id="${d.substring(0, 4)}">${d}</a>`)
)
if($('#all').hasClass('active') == true) {
$('.ecodes').remove();
}
});
$('.filter-option').on('click', function() {
let text = $(this).text();
let selected = $(this).prop('id');
$(this).parent().parent().children('a').text(text);
$(this).parent().parent().children('a').data().selected = selected;
filters[$(this).parent().parent().children('a').prop('id').replace('-','_')] = selected;
$.each($(this).parent().children('a'), function(i,d)
$(d).removeClass('active'); });
$(this).addClass('active');
});
Is there something wrong with my code? I cant seem to figure out why my links aren't working. I need onClick for them to have the class active.
You should use the static element as a starter then delegating the dynamic node(child node) inside the on method
$('dropdown-menu').on('click','.filter-option', function() {
let text = $(this).text();
let selected = $(this).prop('id');
$(this).parent().parent().children('a').text(text);
$(this).parent().parent().children('a').data().selected = selected;
filters[$(this).parent().parent().children('a').prop('id').replace('-','_')] = selected;
$.each($(this).parent().children('a'), function(i,d)
$(d).removeClass('active'); });
$(this).addClass('active');
});
You have to delegate the click to the parent element that exists in the page before you inject new links.
jQuery's on method accepts a selector as the second argument so you can update the following line:
$('.dropdown-menu').on('click', '.filter-option', function() {
let text = $(this).text();
let selected = $(this).prop('id');
$(this).parent().parent().children('a').text(text);
$(this).parent().parent().children('a').data().selected = selected;
filters[$(this).parent().parent().children('a').prop('id').replace('-','_')] = selected;
$.each($(this).parent().children('a'), function(i,d)
$(d).removeClass('active'); });
$(this).addClass('active');
});
Read more: http://api.jquery.com/on/#direct-and-delegated-events

Knockoutjs binds correctly however href on a tag doesn't redirect to the page

I have this html:
<ul class="nav nav-tabs ilia-cat-nav" data-toggle="dropdown" data-bind="foreach : Items" style="margin-top:-30px">
<li role="presentation" data-bind="attr : {'data-id' : ID , 'data-childCount' : Children().length}" style="padding-left: 20px; padding-right: 20px; text-align: center; color: white" class="active-li">
<label id="menu1" data-toggle="dropdown" data-bind="text: Name"></label>
<ul class="dropdown-menu" data-bind="foreach: Children" role="menu" aria-labelledby="menu1">
<li role="presentation"><a role="menuitem" data-bind="text: Name, attr: { 'href': Url} "></a></li>
</ul>
</li>
</ul>
That creates my menu on top using knockoutjs, it works perfectly and href attribute on a tag is filled correctly like href="/site/models#{"catId": "76b4a8ed-1350-46af-8184-3b68029cbd22"}" however when i click on the item, it doesn't redirect to new page. my first thought was maybe its because of hash but it wasn't, so i tried to use target attribute for any of the _self and all others it doesn't work. so my next guess was that there is a javascript method overriding this, so far i haven't found anything. so my question is why doesn't it work?
KnockOut ViewModel:
landing.dataModels.Category = function (_id, _categoryTypeId, _name, _description, _parentId, _children) {
var self = this;
this.ID = ko.observable(_id);
this.CategoryTypeId = ko.observable(_categoryTypeId);
this.Name = ko.observable(_name);
this.Description = ko.observable(_description);
this.ParentId = ko.observable(_parentId);
this.Url = ko.computed(function () {
return '/site/models#{"catId": "' + self.ID() + '"}';
});
this.Children = ko.observableArray([]);
this.getChildren = ko.computed(function () {
return self.Children();
});
_.each(_children, function (item) {
self.Children.push(new landing.dataModels.Category(item.ID, item.categoryTypeId, item.Name, item.Description, item.ParentId, item.Children));
});
};
Update
I have to say that when i right-click on the item and open in new window it does work and shows the page, but its not working on direct left click.
Probably the problem is in the quotes in the generated URL:
href="/site/models#{"catId": "76b4a8ed-1350-46af-8184-3b68029cbd22"}"
The value for href is actually "/site/models#{" leaving the rest of the URL as invalid HTML.
You could try to bind to the escaped URL:
this.Url = ko.computed(function () {
return encodeURI('/site/models#{"catId": "' + self.ID() + '"}');
});
Finally i got tired and i just went with a simple jquery click to make it work:
$(document).ready(function () {
setTimeout(function () {
$(document).on("click", ".ilia-catLink", function () {
var a = $(this).attr("href");
window.location = a;
});
}, 100);
It works this way, but i still wonder why wouldn't that href work on itself.

jQuery detect if document contains an id matching the href of a link

I've written a function that adds hrefs to an alphabetical navigation bar. I made it so each letter section gives itself an ID. I want to make it so in the event there isn't for example a "C" section, I could add a class to the link linking to #c that would disable it. Here's what I have so far:
<ul class="no-bullet inline">
<li><a class="scroller"><strong>A</strong></a></li>
<li><a class="scroller"><strong>B</strong></a></li>
<li><a class="scroller"><strong>C</strong></a></li>
</ul>
<div class="space-above space-below letter-section">
<h4 class="alpha-heading"><strong>A</strong></h4>
<ul class="no-bullet">
<li><a class="naming" href="#">Benny Goodman</a></li>
<li><a class="naming" href="#">Benny Goodman</a></li>
<li><a class="naming" href="#">Benny Goodman</a></li>
</ul>
</div>
<div class="space-above space-below letter-section">
<h4 class="alpha-heading"><strong>A</strong></h4>
<ul class="no-bullet">
<li><a class="naming" href="#">Benny Goodman</a></li>
<li><a class="naming" href="#">Benny Goodman</a></li>
<li><a class="naming" href="#">Benny Goodman</a></li>
</ul>
</div>
<script>
function alphaLink() {
var alphaLink = $(this);
var alphaLinkRef = "#" + alphaLink.text().toLowerCase();
$(alphaLink).attr("href", alphaLinkRef);
};
$('.scroller').each(alphaLink);
//assigns each content section an ID
function alphaID() {
var section = $(this);
var sectionID = section.text().toLowerCase();
$(section).attr("ID", sectionID);
};
$('.alpha-heading').each(alphaID);
linkMatch function(){
var link = $(this);
if(link.length <= 0) {
$(this).addclass("disabled");
}
$("scroller").each(linkMatch);
</script>
If the HREF is something like '#C', take a look at this:
$(document).ready(function(){
$('a').each(function(i,e){
var href = $(this).attr('href')
if(!findID(href)){
// Doesn't exist
$(this).addClass('disabled');
}
})
function findID(ID){
var exists = false;
if($(ID).length > 0){
exists = true;
}
return exists;
}
})
Hope this helps!
UPDATED! Sorry I overlooked that you wanted to disable the link, not on click. Here is a JsFiddle if you inspect the link with href="$find-someting-else" you'll see it has the class disabled whereas the other one does not.
I took Jeremiah's code and altered it slightly to do what I needed it to do. Thanks so much for all the answers- here was the final product:
function findID(ID) {
var exists = false;
if ($(ID).length > 0) {
exists = true;
}
return exists;
}
function matchLink() {
var href = $(this).attr('href');
if (!findID(href)) {
// Doesn't exist
$(this).addClass('alpha-disabled');
}
};
$('.scroller').each(matchLink);
You can do it like this. Here is an example:
function linkMatch(index, elem){
var link = elem,
heading = $(".alpha-heading");
var linkHref = link.attr("href").substring(1, link.attr("href").length);
if(typeof(heading[index]) != "undefined") {
if(linkHref != heading[index].getAttribute("id")) {
link.addClass("disabled");
}
}
}
$(".scroller").each(function(index) {
linkMatch(index, $(this));
});
Edit
I've just edited my code, because I forgot to write length inside linkHref variable

Using an active 'li' element to determine a video's source file

I tried creating a small video library where one div is split into two parts: 1) a menu on the left with the titles of the movies and 2) the rest of the div on the right being a video window that changes it's video source according to the selected title on the menu. I gave the li elements that housed the titles id's and used jQuery/JavaScript to retrieve the title and to assign a new video source based on that title, but it isn't working and I also can't claim to completely understand what I've done. The code is as follows:
HTML
<div class="miyazaki">
<div class="menu">
<ul>
<li><a id="Gulliver">Gulliver's Travels</a></li>
<li><a id="Howl">Howl's Moving Castle</a></li>
<li><a id="Kiki">Kiki's Delivery Service</a></li>
<li><a id="Castle">Castle of Cagoliostro</a></li>
<li><a id="Totoro">"My Neighbor Totoro</a></li>
<li><a id="Ponyo">Ponyo</a></li>
<li><a id="Mononoke">"Princess Mononoke</a></li>
<li><a id="Spirited">Spirited Away</a></li>
<li><a id="Sky">The Sky's Castle Laputa</a></li>
<li><a id="Nausicaa">Nausicaa Valley of the Wind</a></li>
<li><a id="Cat">"The Cat Returns</a></li>
</ul>
</div>
</div>
JavaScript
function Hayato() {
var movie = $("ul.menu li a.active");
if (movie.id == Gulliver || movie.id == null || movie.id == "") {
document.getElementsByClassName('window').video.source.src = Gulliver.mkv
}
else if (movie.id == Howl) {
document.getElementsByClassName('window').video.source.src = Howl.mkv
}
else if (movie.id == Kiki) {
document.getElementsByClassName('window').video.source.src = Kiki.mkv
}
else if (movie.id == Castle) {
document.getElementsByClassName('window').video.source.src = Castle.mkv
}
else if (movie.id == Totoro) {
document.getElementsByClassName('window').video.source.src = Totoro.mkv
}
else if (movie.id == Ponyo) {
document.getElementsByClassName('window').video.source.src = Ponyo.mkv
}
else if (movie.id == Mononoke) {
document.getElementsByClassName('window').video.source.src = Mononoke.mkv
}
else if (movie.id == Spirited) {
document.getElementsByClassName('window').video.source.src = Spirited.mkv
}
else if (movie.id == Sky) {
document.getElementsByClassName('window').video.source.src = Sky.mkv
}
else if (movie.id == Nausicaa) {
document.getElementsByClassName('window').video.source.src = Nausicaa.mkv
}
else (movie.id == Cat) {
document.getElementsByClassName('window').video.source.src = Cat.mkv
}
}
I'm not entirely sure this code is the best way to go about solving my problem, but it's the most logical progression I can think of.
This can all be condensed down considerably since most of the code stays the same in all cases. Also, your closing <ul> isn't a close tag and you are missing a closing <div>.
// Get all the <a> elements
var anchors = document.querySelectorAll(".menu a");
// Get a reference to the video element
var v = document.querySelector("video");
// Set up click event handlers for each
Array.prototype.slice.call(anchors).forEach(function(anchor){
anchor.addEventListener("click", function(evt){
// default video when no id is present
var d = "Gulliver.mkv";
// Use the default or the id
v.source = (!anchor.id) ? d : anchor.id + ".mkv";
console.log("video source is: " + v.source);
});
});
<div class="miyazaki">
<div class="menu">
<ul>
<li><a id="Gulliver">Gulliver's Travels</a></li>
<li><a id="Howl">Howl's Moving Castle</a></li>
<li><a id="Kiki">Kiki's Delivery Service</a></li>
<li><a id="Castle">Castle of Cagoliostro</a></li>
<li><a id="Totoro">"My Neighbor Totoro</a></li>
<li><a id="Ponyo">Ponyo</a></li>
<li><a>Porco Rosso</a></li>
<li><a id="Mononoke">"Princess Mononoke</a></li>
<li><a id="Spirited">Spirited Away</a></li>
<li><a id="Sky">The Sky's Castle Laputa</a></li>
<li><a id="Nausicaa">Nausicaa Valley of the Wind</a></li>
<li><a id="Cat">"The Cat Returns</a></li>
</ul>
</div>
</div>
<video></video>
As you also tagged jQuery here a working example for that:
$('.menu li a').on('click', function() {
var id = $(this).attr('id');
$('.window video source').attr('src', id + '.mkv');
});
Example
Note: Your html is invalid too. The ul is never closed
There's no need to use all these if blocks, you can do it in a one line statement.
You could just do it this way:
function Hayato() {
var movie = $("ul.menu li a.active").attr("id");
if(movie && movie !== "#")
document.getElementsByClassName('window')[0].video.source.src = movie + ".mkv";
}
Note:
In the code you used all the Strings are inavlid Strings, you should wrap them between two " or '.

data-plugin-options filter is not working

I'm using this JessicaWhite free webtemplate (http://www.html5xcss3.com/2014/02/jessicawhite-responsive-html5-theme.html). I'm trying to set a filter in my image portfolio in order to show images of defined filter by default and not all images.
I've tried many things (data-plugin-options='{"filter": ".category01")'), but no luck.
HTML:
<ul id="filters" class="option-set" data-option-key="filter" data-plugin-options='{"filter": ".category01"}'>
<li>All</li>
<li>Category01</li>
<li>Category02</li>
</ul>
I have also tried to switch ' for " within the data-plugin-options, but no luck.
Here is the JS for "option-set":
/* SORTING */
$(function(){
var $container = $('.projects');
$container.isotope({
itemSelector : '.element'
});
var $optionSets = $('#options .option-set'),
$optionLinks = $optionSets.find('a');
$optionLinks.click(function(){
var $this = $(this);
// don't proceed if already selected
if ( $this.hasClass('selected') ) {
return false;
}
var $optionSet = $this.parents('.option-set');
$optionSet.find('.selected').removeClass('selected');
$this.addClass('selected');
// make option object dynamically, i.e. { filter: '.my-filter-class' }
var options = {},
key = $optionSet.attr('data-option-key'),
value = $this.attr('data-option-value');
// parse 'false' as false boolean
value = value === 'false' ? false : value;
options[ key ] = value;
if ( key === 'layoutMode' && typeof changeLayoutMode === 'function' ) {
// changes in layout modes need extra logic
changeLayoutMode( $this, options )
} else {
// otherwise, apply new options
$container.isotope( options );
}
return false;
});
});
Per the below comments, try the following:
Remove the 'data-category' attribute from your portfolio items, it's not being used.
Change your 'filter buttons' markup to the following -
<ul id="filters">
<li><a class="filter-button" href="#filter" data-filter="*" class="btn btn-mini">All</a></li>
<li><a class="filter-button" href="#filter" data-filter=".category01" class="btn btn-mini selected">Category01</a></li>
<li><a class="filter-button" href="#filter" data-filter=".category02" class="btn btn-mini">Category02</a></li>
</ul>
Comment out the entire "sorting" JS function and replace with this -
var $projects = $('.projects').isotope({
filter: '.category 01'
});
$('.filter-button').on( 'click', function() {
var filteredVal = $(this).attr('data-filter');
$projects.isotope({ filter: filteredVal });
$('.filter-button.selected').removeClass('selected');
$(this).addClass('selected');
});

Categories