How to access links within repeat control via CSJS in XPages? - javascript

In my application I display a link in a repeat control. This link will open a dialog control which displays details for a chosen row in the repeat.
Now I want to make the links appear as "read" when they are clicked.
I have defined the following function that will register the link ID clicked in a cookie and change the CSS color property of the link.
I can store the link ID in a cookie but when I try to find it in the DOM and change the CSS I fail. What am I doing wrong?
// onclick
function saveId(id) {
if ($.cookie('idCookie')) {
$.cookie('idCookie', $.cookie('idCookie') + "," + id);
} else {
$.cookie('idCookie', id);
}
}
// make all links colored
function setVisited() {
if (null != $.cookie('idCookie')) {
var idArray = $.cookie('idCookie').split(',');
console.log("#ids:" + idArray.length);
for (var x = 0; x < idArray.length; x++) {
console.log("ID: " + x + "=" + idArray[x]);
if ($('#' + idArray[x]).length) {
//link exists
$('#' + idArray[x]).css('color', 'red');
}
}
}
// assign saveId()
$(document).ready(function() {
$('a').click(function() {
saveId($(this).attr('id'));
});
setVisited();
});

The problem is that you cannot use the : in your selector as described here:
How to get the element id in repeat control
so your code must look something like this:
// onclick
function saveId(id) {
if ($.cookie('idCookie')) {
$.cookie('idCookie', $.cookie('idCookie') + "," + id);
} else {
$.cookie('idCookie', id);
}
}
// make all links colored
function setVisited() {
if (null != $.cookie('idCookie')) {
var idArray = $.cookie('idCookie').split(',');
for (var x = 0; x < idArray.length; x++) {
var link = $(document.getElementById(idArray[x])).get();
if (link.length) {
$(link).css('color', 'red');
}
}
}
}
// assign saveId()
$(document).ready(function() {
$('a').click(function() {
saveId($(this).attr('id'));
});
setVisited();
});
good luck!

You probably need to use the x$ jQuery selector as your ids contains colons: https://openntf.org/XSnippets.nsf/snippet.xsp?id=x-jquery-selector-for-xpages.

Related

Script that change the HTML-content of another page?

On my first page I have two input boxes and a button that will add the input to localStorage. When the data has been added I want to trigger an event that will write out the contents of localStorage on ANOTHER page. My problem is that my script can't find the element on the second page.
Code that adds the data to localStorage:
$("#submitLocal").click(function () {
var key = inputKey.value;
var value = inputValue.value;
localStorage.setItem(key, value);
if (newWindow == null || newWindow.closed) {
newWindow = window.open("local.html", "localWindow");
}
window.dispatchEvent(new Event("storage"));
});
I add the event listener:
window.addEventListener("storage", myFunc);
Which calls the function:
function myFunc(event) {
document.getElementById("addInfo").innerHTML = "";
for (var i = 0; i < localStorage.length; i++) {
$("#addInfo").append(
localStorage.key(i) +
" " +
localStorage.getItem(localStorage.key(i)) +
"<br>"
);
}
}
Right now, the element "addInfo" is on the FIRST page, and the data in localStorage gets written out on the page. But how can I do to write it on the second page if it cant find the elements on that page?
Im new to stackoverflow so I hope I managed to describe the problem well enough.
Thanks in advance.
It ALWAYS helps to post relevant code. In this case what is $("#submitLocal") ? If it is a submit button in a form, use the form submit event and preventDefault!
Why dispatch events in an event?
Just use the one you are in and the load event in page2
main page
$("#myForm").on("submit", function (e) {
e.preventDefault();
var key = inputKey.value;
var value = inputValue.value;
localStorage.setItem(key, value);
if (newWindow == null || newWindow.closed) {
newWindow = window.open("local.html", "localWindow");
}
});
local.html
function myFunc(event) {
$("#addInfo").empty();
for (var i = 0; i < localStorage.length; i++) {
$("#addInfo").append(
localStorage.key(i) +
" " +
localStorage.getItem(localStorage.key(i)) +
"<br>"
);
}
}
window.addEventListener("load",myFunc)

How to clear table inside a dialog when dialog is closed

When the button is clicked, 2 sets data is added. I use material design.
Button needs 2 clicks to run function for first time. Due to this, the data is added to table 2 times.
Code
HTML
<button onclick="purchaseList(orderid)" id="dialog">Button</button>
JS
function popup(listid) {
var starCountRef = firebase.database().ref('Orders/' +
listid).child('foodItems');
starCountRef.on('child_added', snapshot => {
var snaps = snapshot.val();
var itemPrice = snaps.price;
var itemName = snaps.productName;
var itemQuantity = snaps.quantity;
console.log(itemName);
$("#producttable").append(
'<tr><td class="mdl-data-table__cell--non-numeric">' + itemName +
'</td><td>' + itemQuantity + '</td><td>' + itemPrice + '</td></tr>'
);
});
var dialog = document.querySelector('dialog');
var showDialogButton = document.querySelector('#dialog');
if (!dialog.showModal) {
dialogPolyfill.registerDialog(dialog);
}
showDialogButton.addEventListener('click', function() {
dialog.showModal();
});
dialog.querySelector('.close').addEventListener('click', function() {
var element = document.getElementById("producttable")
while (element.lastChild) {
element.removeChild(element.lastChild);
}
dialog.close();
});
}
This should work:
var element = document.getElementById("producttable")
while (element.lastChild) {
element.removeChild(element.lastChild);
}
Add this as necessary.
I suggest you change your firebase function from using .on to .once to avoid multiple additions of data to your table and as your data isn't expected to change frequently or require active listening you better use .once for performance benefits.
firebase.database().ref('Orders/' +
listid + '/foodItems').once('value').then(function(snapshot) {
// the rest of your code goes here
});
this remocve element with class name ".mdl-data-table__cell--non-numeric"
when user click .close
dialog.querySelector('.close').addEventListener('click', function () {
dialog.close();
$(".mdl-data-table__cell--non-numeric").remove();
});
UPDATE:
to open dialog on 2nd click use pseudo element to activate like this
<div class=pseudo><button onclick="purchaseList(orderid)"id="dialog" disabled>Button</button></div>
var i=0;
$('.pseudo').click(function(){
i++;
if(i==2){
$("#dialog").prop('disabled',false);
}
});

how to make the jquery function load before one ajax function finish

How do I fire one event before the previous function completed its function?
I have the following AJAX code :
var BrainyFilter = {
//...
init: function (opts) {},
changeTotalNumbers: function (data) {
jQuery(BrainyFilter.filterFormId).find('.bf-count').remove();
jQuery(BrainyFilter.filterFormId).find('option span').remove();
jQuery(BrainyFilter.filterFormId).find('select').removeAttr('disabled');
jQuery('.bf-attr-filter').not('#bf-price-container').find('input, option')
.attr('disabled', 'disabled')
.parents('.bf-attr-filter')
.addClass('bf-disabled');
if (data && data.length) {
for (var i = 0; i < data.length; i++) {
jQuery('.bf-attr-' + data[i].id + ' .bf-attr-val').each(function (ii, v) {
if (jQuery(v).text() == data[i].val) {
var parent = jQuery(v).parents('.bf-attr-filter').eq(0);
var isOption = jQuery(v).prop('tagName') == 'OPTION';
var selected = false;
if (isOption) {
jQuery(v).removeAttr('disabled');
selected = jQuery(v)[0].selected;
} else {
parent.find('input').removeAttr('disabled');
selected = parent.find('input')[0].checked;
}
parent.removeClass('bf-disabled');
if (!selected) {
if (!isOption) {
parent.find('.bf-cell').last().append('<span class="bf-count">' + data[i].c + '</span>');
} else {
jQuery(v).append('<span> (' + data[i].c + ')</span>');
}
}
}
});
}
jQuery('.bf-attr-filter input[type=checkbox]').filter(':checked')
.parents('.bf-attr-block').find('.bf-count').each(function (i, v) {
var t = '+' + jQuery(v).text();
jQuery(v).text(t);
});
// since opencart standard filters use logical OR, all the filter groups
// should have '+' if any filter was selected
if (jQuery('.bf-opencart-filters input[type=checkbox]:checked').size()) {
jQuery('.bf-opencart-filters .bf-count').each(function (i, v) {
var t = '+' + jQuery(v).text().replace('+', '');
jQuery(v).text(t);
});
}
}
// disable select box if it hasn't any active option
jQuery(BrainyFilter.filterFormId).find('select').each(function (i, v) {
if (jQuery(v).find('option').not('.bf-default,[disabled]').size() == 0) {
jQuery(v).attr('disabled', 'true');
}
});
},
//...
} // close the BrainyFilter
I also have another jQuery file running to get the bf-count value using $('.bf-count').text().
When the page load, the bf-count value is empty. Since the code above inject the bf-count, I will need to wait until it finishes the for loop in order to get the bf-count value.
What is the best way to approach this?
without knowing how the second js file is loaded, I can only give you a guesstimate suggestion.
If you want to run the second js file code after the page is fully loaded, you can wrap the code in:
jQuery(window).load(function(){
//your code here. runs after the page is fully loaded
});
jQuery documentation: http://api.jquery.com/load-event/
"The load event is sent to an element when it and all sub-elements have been completely loaded. This event can be sent to any element associated with a URL: images, scripts, frames, iframes, and the window object."

Match url folders with a tag href to make an active state

I made an active state for my menu on a certain urls. I have urls like this:
/products/other-clothing/sporting/adults-anzac-australia-polo
/products/other-clothing/sporting/adults-nz-tee
/products/bags/backpacks
My code gets the folder from after the / so other-clothing, sporting, etc.
It is working fine, I just assume there is a more efficient way to write the code.
Here is my code:
jQuery(".product-nav li a").each(function() {
// URL url
var cat = location.pathname.split("/")[2];
var subcat = location.pathname.split("/")[3];
var c = "/products/" + cat + "/" + subcat;
// A tag url
var acat = this.href.split("/")[4];
var asubcat = this.href.split("/")[5];
var e = "/products/" + acat + "/" + asubcat;
if(e == c) {
jQuery(this).parent().addClass("active");
jQuery(this).parent().parent().parent().addClass("active");
}
});
If anyone can provide a cleaner way of writing the code that'd be great. I probably dont need "/products/" +.
Notice the output of the following expressions:
$('')[0].href;
/*
* http://stackoverflow.com/questions/7564539/match-url-folders-with-a-tag-href-to-make-a-active-state
*/
$('').eq(0).attr('href');
/*
* /questions/7564539/match-url-folders-with-a-tag-href-to-make-a-active-state
*/
So, if your <a> tags contain URLs that start with / then you can compare the .attr('href') with location.pathname. For testing, try running this in console from this page:
$('a').each(function () {
if ($(this).attr('href') == location.pathname) {
$(this).css({
'font-size': '40px',
'background-color': 'lime'
});
}
});
Here's a brief whack at it:
jQuery(".product-nav li a").each(function() {
// URL url
var c = location.pathname.split('/').slice(2, 4)
// A tag url
, e = this.href.split('/').slice(4, 6)
;
if(e[0] == c[0] && e[1] == c[1]) {
jQuery(this).parentsUntil(
'div:not(.subnav)', // go up the tree until the 1st div that isn't .subnav
'.product-nav li, .subnav' // and only match these parents
).addClass('active');
}
});
.parent().parent().parent()... has a pretty bad code smell to it but can't be improved without a look at your markup. You should probably be using .closest() instead.
Interesting question. Here is my attempt to clean it up:
jQuery(function ($) {
function Category(outer, inner) {
this.outer = outer
this.inner = inner
}
Category.fromURL = function (url) {
var parts = url.replace(/^(https?:\/\/.*?)?\//, "").split("/")
return new Category(parts[1], parts[2])
}
Category.prototype.equals = function (other) {
return this.outer === other.outer
&& this.inner === other.inner
}
var category = Subcategory.fromURL(location.href)
$(".product-nav a").each(function () {
if (Category.fromURL(this.href).equals(category)) {
$(this).closest("li.inner").addClass("active")
$(this).closest("li.outer").addClass("active")
}
})
})

Is there a way to convert this jquery code to javascript?

I'm trying to create a tab menu. And I need this coded in regular javascript, not jquery.
$(document).ready(function() {
//When page loads...
$(".general_info_content").hide(); //Hide all content
$("ul.general_info_tabs li:first").addClass("active").show(); //Activate first tab
$(".general_info_content:first").show(); //Show first tab content
//On Click Event
$("ul.general_info_tabs li").click(function() {
$("ul.general_info_tabs li").removeClass("active"); //Remove any "active" class
$(this).addClass("active"); //Add "active" class to selected tab
$(".general_info_content").hide(); //Hide all tab content
var activeTab = $(this).find("a").attr("href"); //Find the href attribute value to identify the active tab + content
$(activeTab).fadeIn(); //Fade in the active ID content
return false;
});
});
The core of what you want to do is below - I'm sure there are a thousand different ways to do each task:
Remove a CSS class from an element:
var classes = document.getElementById([id]).className.split(" ");
for(var i = 0; i < classes.length; i++)
if(classes[i] == removeClass)
classes[i] = "";
document.getElementById([id]).className = classes.join(" ");
Add a CSS class to an element:
document.getElementById([i]).className += " " + addClassName;
Hide an element:
document.getElementById([i]).style.display = "none";
Fade an element:
// not tested, but based on tested/used code
function fade(el, opacity, fadeInTime) {
if (opacity < 100) {
el.style.opacity = opacity / 100;
el.style.filter = "alpha(opacity=" + opacity + ")";
opacity += 5;
setTimeout(function () { fade(el, opacity, fadeInTime); }, fadeInTime / 5);
}
}
To find all elements by CSS and tag name:
var matches = new Array();
var all = document.getElementByTagName(searchTagName);
for(var i = 0; i < all.length; i++){
if(all[i].className.replace(searchClassName, "") != all[i].className) {
matches.push(all[i].className);
}
}
// do something with (i.e., return or process) matches
And for the record, I find it encouraging, not unreasonable, that a person using the jQuery library wants to know how to do get things done with native JS/DOM.
More functions to complement Brian's post. Good luck.
EDIT: As I mentioned I would change the class=general_info_content to id=general_info_content1.
function attach(el, event, fnc) {
//attach event to the element
if (el.addEventListener) {
el.addEventListener(event, fnc, false);
}
else if (document.attachEvent) {
el["on" + event] = fnc; // Don not use attachEvent as it breaks 'this'
}
}
function ready() {
// put all your code within $(function(){}); here.
}
function init() {
attach(document, "readystatechange", function () {
if (document.readyState == "complete") {
ready();
}
});
}

Categories

Resources