I have below mark-up . I am doing some DOM manipulation.I am trying to do using vanila js instead of jquery .
In jQuery i am writing like this
var $window = $(window),
$container = $('.rc105w1'),
$categories = $('.rc105w2'),
$counts = $('.rc105count'),
$productLists = $('.rc105w3'),
vdub = window.innerWidth,
resizeTimeout;
labelCategories();
function labelCategories() {
var row = 1,
prevoffset = 0,
guid = 0,
offset;
$categories.each(function() {
var $category = $(this),
$productList = $category.find($productLists),
$link = $category.find('> a');
console.log($productList.length,'product length')
console.log($link.length,'link length')
});
}
})
using this line $category.find($productLists) I am checking number of descendent or matching elements
I want to do same thing using vanilla js .I tried like this
function init(){
console.log('javascript code start')
var $window = window,
$container = document.querySelectorAll('.rc105w1'),
$categories = document.querySelectorAll('.rc105w2'),
$counts = document.querySelectorAll('.rc105count'),
$productLists = document.querySelectorAll('.rc105w3'),
vdub = window.innerWidth,
resizeTimeout;
labelCategories();
function labelCategories() {
var row = 1,
prevoffset = 0,
guid = 0,
offset;
$categories.forEach(function(el) {
var $category = el,
$productList = $category.querySelectorAll($productLists),
$link = $category.querySelectorAll('> a');
console.log($productList.length,'javasscript $productList length ')
console.log($link.length ,'javasscript $link length ')
});
}
}
function docReady(fn) {
// see if DOM is already available
if (document.readyState === "complete" || document.readyState === "interactive") {
// call on next available tick
setTimeout(fn, 1);
} else {
document.addEventListener("DOMContentLoaded", fn);
}
}
docReady(init)
I am not able to find matching element or descendent elements any way to find using javascript ?
<section class="rc105 rc105v0">
<div class="cwidth">
<div class="rc105w1">
<div class="rc105w2 rc105w2-bttn">
<a href="/cloud/migrate-applications-to--cloud/">
<span> Applications</span>
</a>
</div>
<div class="rc105w2 rc105w2-bttn">
<a href="/cloud/migrate-custom-applications-to-cloud/">
<span>Custom Applications</span>
</a>
</div>
</div>
<div class="rc105w1 rw-scrim-neutral-40bg">
<div class="rc105w2 rc105w2-drawer rc105w2-6up rc105w2-12set rc105w2-tallbttn">
<a href="#developer-services">
<span>Developer Services</span>
</a>
<div class="rc105w3">
<h3>Developer Services</h3>
<p>Build, deploy, and manage modern cloud applications using developer friendly tools and services.</p>
<div class="rc105w4">
<div class="rc105w5 rc105w5-half">
<h4>Build and run</h4>
<ul class="rc105linklist rc105w5-2col">
<li>API Gateway</li>
<li>API Management</li>
</ul>
</div>
<div class="rc105w5 rc105w5-quarter">
<h4>Low code</h4>
<ul class="rc105linklist">
<li>Application Express (APEX)</li>
<li>Visual Builder Studio</li>
</ul>
</div>
<div class="rc105w5 rc105w5-quarter">
<h4>Extend</h4>
<ul class="rc105linklist">
<li>Application Integration</li>
<li>Content Management</li>
</ul>
</div>
</div>
</div>
</div>
<div class="rc105w2 rc105w2-drawer rc105w2-6up rc105w2-12set rc105w2-tallbttn">
<a href="#containers-and-functions">
<span>Containers and Functions</span>
</a>
<div class="rc105w3">
<h3>Containers and Functions</h3>
<p>Deploy microservices applications on high-performance, managed open source Docker, Kubernetes, and Fn Functions services.</p>
<div class="rc105w4">
<div class="rc105w5">
<ul class="rc105linklist">
<li>Functions</li>
<li>Kubernetes Engine</li>
<li>Registry</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
querySelectorAll() expects a selector not a (static) Nodelist.
To make your code work you can just pass the selector like you do with $link.
$productList = $category.querySelectorAll('.rc105w3')
Maybe the problem occurs when you try to use querySelectorAll, because it will provide you an array, so try using querySelector instead of querySelectorAll and also querySelectorAll expects a selector not a Nodelist
Related
<ul>
<li>
<div class="link" id="contentLink20000002">
Link 1
</div>
</li>
<li>
<div class="link" id="contentLink1000002">
Link 2
</div>
</li>
<li>
<div class="link" id="contentLink2000003">
Link 3
</div>
</li>
<li>
<div class="link" id="contentLink2000004">
Link 4
</div>
</li>
</ul>
I have this structure an I am trying to separate id's which starts with 'contentLink2'. I have tried achieving this with .contains and regex but no luck so far.
var listids = $('ul li div');
listids.each(function(li){
var contentId = $(this).filter('contentLink2').attr('id');
console.log(contentId);
});
What i am trying is to create navigation. Like
Text
link1
link2
Text
link3
link4
HTML is dynamic so I don't have control it.
just use the attr to get to the id
var listids = $('div.link');
listids.each(function(index, element){
var contentId = $(this).attr('id');
// or use the second paramater to access the element
// var contentId = $(element).attr('id');
console.log(contentId.indexOf('contentLink2') !== -1);
});
Can do this with a jQuery attribute selector
listids.filter('[id^=contentLink2]').doSomething()
use JS instead
var x = document.getElementsByTagName('DIV');
for(i = 0 ; i < x.length ; i++){
var y = document.getElementsByTagName('DIV')[i];
var z = y.getAttribute('ID');
var m = z.search('contentLink2');
if(m == -1){
// NO THING
}else{
// Do Some Thing Here
};
}
I guess this what you are looking for.
The following code works, but I think there's room for improvement. The index check is there because after the first element is removed the next element looks like it has an index of -1, but is actually the previously removed element. Then it iterates again and finds the clicked element and removes it. BUT since the index is -1 on the first go around the wrong group gets deleted.
How do I keep the zombie elements from being iterated on more efficiently? This is in a backbone view with an in page confirmation.Thanks.
EDIT: To add HTML
Group section always has a default group that shouldn't be deleted.
<div class="section-border-top--grey js-favorite-group">
<h4 class="expandable__cta cta--std-teal js-expand-trigger"><span class="icon icon-plus--teal expandable__cta-icon"></span>All Doctors</h4>
<div class="expandable__content js-favorite-doctor-row-container" aria-expanded="true">
<div class="location-section dr-profile">
<div class="section__content js-doctor-row">
<div class="favorite-doctor-manage__row">
DR info
</div>
</div><!--/section__content-->
</div><!--/location-section-->
</div><!--/expandable__content-->
Tag section to remove groups
<div class="js-favorite-doctor-manage-add-remove">
<div class="grid-construct">
<div class="expandable" data-controller="expandable">
<ul class="tag-list js-group-list" tabindex="-1">
<li class="tag tag--teal" >
Lauren's Doctors
<ul class="tag-sub">
<li><button class="tag-icon tag-icon--close-white js-group-remove">Remove group: Lauren's Doctors</button></li>
</ul>
</li>
<li class="tag tag--teal" >
Timmy's Doctors
<ul class="tag-sub">
<li><button class="tag-icon tag-icon--close-white js-group-remove">Remove group: Timmy's Doctors</button></li>
</ul>
</li>
</ul>
</div>
removeGroup: function( evt ) {
var deleteGroup = function() {
if ( $(evt.currentTarget).closest('.tag').hasClass('is-active')){
var clickedTag = $(evt.currentTarget).closest('.tag');
var groupList = this.$el.find('.js-group-list');
var groupTags = groupList.find('.tag');
var index = groupTags.index(clickedTag);
var groupSections = $('.js-favorite-group');
// add one to account for "All" section which is never removed
var groupToRemove = groupSections.eq(index + 1);
console.log(groupToRemove);
var removedGroupName = this.getGroupNameForSection(groupToRemove);
var allDoctors = groupSections.eq(0);
var allDoctorsContainer = allDoctors.find('.js-favorite-doctor-row-container');
if ( index > -1 ){
groupToRemove.find('.js-favorite-doctor-row').appendTo(allDoctorsContainer);
clickedTag.remove();
groupToRemove.remove();
this.updateSectionDropdowns();
this.ariaAlert('Group ' + removedGroupName + ' removed');
this.hideConfirm(evt);
}
}
};
this.showAlert(evt, deleteGroup);
},
showAlert: function (evt, callback) {
that = this;
var clickedTag = '';
clickedTag = $(evt.currentTarget).closest('.tag');
clickedTag.addClass('is-active').attr('data-delete','true');
$('.delete-acct-message').show().focus();
$('.js-remove-yes').on('click', function(evt){
evt.preventDefault();
callback.apply(that);
});
$('.js-remove-no').on('click', function(evt){
evt.preventDefault();
this.hideConfirm(evt);
});
},
I would suggest that you should use custom attributes in your html, this will simplify your javascript logic and make it more effective and efficient.
I have modified your html and javascript to add the support for custom attribute data-doc-group. Have a look at your group sections div here
<div data-doc-group="lauren" class="section-border-top--grey js-favorite-group">
<h4 class="expandable__cta cta--std-teal js-expand-trigger"><span class="icon icon-plus--teal expandable__cta-icon"></span>Lauren's Doctors</h4>
<div class="expandable__content js-favorite-doctor-row-container" aria-expanded="true">
<div class="location-section dr-profile">
<div class="section__content js-doctor-row">
<div class="favorite-doctor-manage__row">
DR info
</div>
</div><!--/section__content-->
</div><!--/location-section-->
</div>
Here are the tags with custom attributes
<li data-doc-group="lauren" class="tag tag--teal">
Lauren's Doctors
<ul class="tag-sub">
<li><button class="tag-icon tag-icon--close-white js-group-remove">Remove group: Lauren's Doctors</button></li>
</ul>
</li>
<li data-doc-group="timmy" class="tag tag--teal">
Timmy's Doctors
<ul class="tag-sub">
<li><button class="tag-icon tag-icon--close-white js-group-remove">Remove group: Timmy's Doctors</button></li>
</ul>
</li>
Here is the javascript to handle this, (this may be a bit buggy, but will give you a general idea)
removeGroup: function(evt) {
this.showAlert(evt, function() {
var $clickedTag = $(evt.currentTarget).closest('.tag'),
dataGroupName,
$groupToRemove,
removedGroupName,
$allDoctors = $('.js-favorite-group').eq(0),
$allDoctorsContainer = $allDoctors.find('.js-favorite-doctor-row-container');
if ($clickedTag.hasClass('is-active')){
dataGroupName = $clickedTag.data('doc-group');
$groupToRemove = $allDoctors.siblings('[data-doc-group="' + docGroupName + '"]');
if ($groupToRemove.length > 0){
$groupToRemove.find('.js-favorite-doctor-row').appendTo($allDoctorsContainer);
$clickedTag.remove();
$groupToRemove.remove();
removedGroupName = this.getGroupNameForSection($groupToRemove);
this.updateSectionDropdowns();
this.ariaAlert('Group ' + removedGroupName + ' removed');
this.hideConfirm(evt);
}
}
});
}
My html page is :
<div data-role="content">
<div id="menu">
<ul id="menu" data-role="listview" class="ui-listview "
data-bind="foreach: menu">
<li>
<a data-bind="text:name, attr: {href: urlmenu}"></a>
<a href="#" data-bind="{ click: $parent.remove }"
data-role="button" data-icon="delete"></a>
</li>
</ul>
</div>
</div>
<div data-role="footer" data-position="fixed">
<div data-role="navbar">
<ul id="footer">
<li>Home</li>
<li>Asignaturas</li>
<li>Mensajes</li>
</ul>
</div>
</div>
And my JS code is :
$( document ).on( "pagebeforechange" , function(e, data) {
var toPage = data.toPage[0].id;
if( toPage == "home"){
ko.cleanNode(document.getElementById('menu'));
menu();
}
});
function menuViewModel(){
var self = this;
self.menu = ko.observableArray([]);
self.menu.removeAll();
self.menu = ko.observableArray([
new EditMenuViewModel("Perfil"),
new EditMenuViewModel("Asignaturas")
]);
}
function EditMenuViewModel(name) {
this.name = ko.observable(name);
this.urlmenu = ko.observable("#"+name);
};
function menu(){
var menuviewModel = new menuViewModel();
ko.applyBindings(menuviewModel, document.getElementById('menu'));
}
When I load my page for the first time everything works fine, but when I click on link footer home, the array content is duplicated.
Example is here:
Any idea?
Thanks
You have two DOM elements with id=menu, a div and a ul.
<div id="menu"> <!-- <-- change this id for example -->
<ul id="menu" data-role="listview" class="ui-listview "
data-bind="foreach: menu">
...
</ul>
</div>
Ids should be unique, you need to change the id on one of your elements, hopefully this will also solve your problem.
Update
As you can read in this thread, ko.cleanNode will not remove items created using foreach binding.
You need to change your approach.
Here is a jsFiddle that reproduces your problem.
What you can do is stop cleaning+applying bindings, and update your observableArray instead:
$( document ).on( "pagebeforechange" , function(e, data) {
var toPage = data.toPage[0].id;
if( toPage == "home"){
menuviewModel.menu.removeAll(); //clear menu
//add whatever menu item you need
menuviewModel.menu.push(new EditMenuViewModel("New Menu1 " + (new Date()).getTime()));
menuviewModel.menu.push(new EditMenuViewModel("New Menu2 " + (new Date()).getTime()));
}
});
function menuViewModel(){
var self = this;
self.menu = ko.observableArray([]);
self.menu.removeAll();
self.menu = ko.observableArray([
new EditMenuViewModel("Perfil"),
new EditMenuViewModel("Asignaturas")
]);
}
function EditMenuViewModel(name) {
this.name = ko.observable(name);
this.urlmenu = ko.observable("#"+name);
};
//bind only once
var menuviewModel = new menuViewModel();
ko.applyBindings(menuviewModel, document.getElementById('menu'));
Here is an example
This is old thread, but I've found a (ugly) way to overcome it:
before the cleaning, I'm caching the observable array values and set it with only 1 value. After the rebind, I'm restoring the cached values. Something like this:
var self = this;
self.myArray = ko.observableArray(['val1', 'val2']);
var tempArray = [];
self.BeforeCleaning = function () {
tempArray = self.myArray()
self.myArray(['temp value']);
};
self.AfterRebinding = function () {
self.myArray(tempArray);
};
horrible, but works for me.
Hello i have cart full with Elements
This Ex of one of them
<div class="item-container cart-item">
<div>
<img border="0" onerror="src='http://www.myengravedjewelry.com/Admin/surfing.jpg'" title="Bloody Mary Style Colour Name Necklace" src="http://www.myengravedjewelry.com/Admin/surfing.jpg" alt="1009">
<div class="item-header">
<div class="item-body">
<ul class="item-ul">
<li>
<li>
<li>
<span class="bold-14">Price:14.9 </span>
</li>
<li>
<span>ShortId:1010 </span>
</li>
<li>
<span>LongId:110-01-073-10 </span>
</li>
<li>
<span class="spanDefCat">DefaultCat:334 </span>
</li>
</ul>
</div>
</div>
<div class="item-footer"></div>
</div>
When i press save i go trow each one of this element and check if DefaultCat==0
var elements = document.getElementsByClassName("cart-item");
and i try to get to this defaulCat like this
for(i=0;i<elements.length;i++){
var elementContent=elements[i].find(".spanDefCat").html();
var vars = elementContent.split(" ");
var obj = {};
vars.forEach(function(v) {
var keyValue = v.split(":");
obj[keyValue[0]] = keyValue[1];
});
DefaultCat = obj["DefaultCat"];
ShortId = elements[i].children[1].alt;//New style to take ShortID
if(DefaultCat==0)setDefaultCatToProductId(parseInt(ShortId));
arrSortedOrder[i]=parseInt(ShortId);
}
Any one know how to get to this value?
p.s
Plz Do NOT give me solution with $(.spanDefCat) because when i find deff=0 i need to take ShordId as Well from this element[i]
Try this:
$(".cart-item").each(function(){
var shortId = $(this).find(".bold-14").parent("li").siblings("li").children("span").html();
var shortItem = shortId.replace(' ','').split(":");
var defaultCat = $(this).find(".spanDefCat").html();
var item = defaultCat.replace(' ','').split(":");
if(item[1]==0){
var id = parseInt(shortItem[1]);
//do something
}else{
var id = parseInt(shortItem[1]);
//do something else
}
console.log(defaultCat);
console.log(shortId);
});
Note: Above code give you the DefaultCat:334 and ShortId:1010 so now you can use both in if else statement.
If the format of DefaultCat:334 is same for all cart item then you can check whether it is 0 or not
JSFIDDLE DEMO
I see JQuery tag so i give you a response with JQuery statements.
$(".cart-item").find(".spanDefCat").each(function(index, domEle){
//get text, delete spaces and split
split_result = $(domEle).text().replace(' ','').split(":");
//get only numeric value as string
defaultCat = split_result[1];
//parse into int
defaultCat = parseInt(defaultCat);
//if your var is equal to 0
if(defaultCat == 0){
/*********************
* Type you code here *
**********************/
}
});
I have this HTML piece of code
<div id="countdown">
<ul>
<li id="giorni"><span class="num red">66</span><span class="lab">Giorni</span></li>
<li id="ore"><span class="num red">23</span><span class="lab">Ore</span></li>
<li id="minuti"><span class="num red">44</span><span class="lab">Minuti</span></li>
<li id="secondi"><span class="num red">14</span><span class="lab">Secondi</span></li>
</ul>
</div>
I want to replace the content of each span that has a num class. In order to do that I have written:
var countdown = {
init: function( config ) {
this.dataX = Date.parse(new Date(2012, 5, 30));
this.adesso = new Date().getTime();
this.giorni = config.container.find('li#giorni');
console.log(this.giorni);
this.count();
},
... some other code ...
};
countdown.init({
container: $('div#countdown ul');
});
I really don't understand why if I try to log this.giorni I get [] in response, but if I write into the console the same code it returns the node I need.
$('#countdown span.num').each(function() {
$(this).empty().html(Math.random() * 1000);
});