jQuery remove string from string doesn't work - javascript

Everytime an certain image is clicked I fetch some information, to add that information to a string and after that replace the current url with the new one. This is my code so far:
jQuery(document).ready(function(){
var kleuren = [];
jQuery('.swatch-category-container img').click(function(){
var kleur = jQuery(this).attr('title');
console.log("Selected kleur: " + kleur);
var link = jQuery(this).closest('.popup').find('.photo a').prop('href');
kleuren.push(kleur);
console.log(kleuren);
console.log(kleuren.length);
console.log("Fetched link: " + link);
var length = kleuren.length -1;
var avoid ="?kleur="+kleuren[length];
console.log("Remove string: " + avoid);
var news_link = link.replace(avoid,'');
var new_link = news_link + "?kleur="+kleur;
console.log("Cut string: " + news_link);
jQuery('.photo').find('.sendkleur').attr("href", new_link);
});
});
This works fine, but the previous data doesn't get removed.
For example
When the first image is clicked the kleur = zwart that info is put in the url.
But when the user clicks another image after that the url will look like ?kleur=zwart?kleur=beige instead just of ?kleur=beige
How can I remove the first part?

Although we could debug the replacement logic, I think I'd come at this a totally different way: Have a data-* attribute on the link that gives the raw version without kleur, then just reuse that; you can even initialize it on the first pass so you don't have to update your markup:
var linkElement = jQuery(this).closest('.popup').find('.photo a');
var link = linkElement.attr("data-rawhref");
if (!link) {
link = linkElement.attr("href");
linkElement.attr("data-rawhref", link);
}
// ...add kleur to `link`
If you don't need it to actually be an attribute, you can use data instead, but there's probably no real advantage over the above as the link is just a string.
var linkElement = jQuery(this).closest('.popup').find('.photo a');
var link = linkElement.data("rawhref");
if (!link) {
link = linkElement.attr("href");
linkElement.data("rawhref", link);
}
// ...add kleur to `link`
But the problem with your code is that you're using the current kleur, rather than the old one, in avoid:
kleuren.push(kleur); // Pushes the current kleur at the end
var length = kleuren.length -1; // Will be the index of the *current* kleur
var avoid ="?kleur="+kleuren[length];// ...and so this is looking for the wrong one
instead:
var avoid, new_link;
if (kleuren.length) {
avoid = "?kleur="+kleuren[kleuren.length - 1];
new_link = link.replace(avoid,'') + "?kleur="+kleur;
} else {
new_link = link + "?kleur="+kleur;
}
kleuren.push(kleur);
That's assuming you really need an array of previously-selected colors. If you don't, just use a variable:
var avoid, new_link;
if (letzteKleur) { // Meant to be "last color", my German is non-existant
avoid = "?kleur="+letzteKleur;
new_link = link.replace(avoid,'') + "?kleur="+kleur;
} else {
new_link = link + "?kleur="+kleur;
}
letzteKleur = kleur;

Maybe because you never do a pop on the array?
How does your log look like?
It seems that you try to replace the current value not the previous.
kleuren.push(kleur);
console.log(kleuren);
console.log(kleuren.length);
console.log("Fetched link: " + link);
var length = kleuren.length -1;
var avoid ="?kleur="+kleuren[length];
maybe that will do (of course only if there is at least 1 item in the array)
console.log(kleuren);
console.log(kleuren.length);
console.log("Fetched link: " + link);
var length = kleuren.length -1;
var avoid ="?kleur="+kleuren[length];
kleuren.push(kleur);

Related

Element selector returning null even after "DOMContentLoaded"?

I'm having some difficulty here with getElementById returning a null object. All of the below code has been placed inside an anonymous function that is called when "DOMContentLoaded" (event listener). I did this to avoid getElementById not being able to find the twitter button when I attempt to set an attribute (particularly "data-text"). The first function has no problem locating the element (an 'a' element on the page) with getElementById, but the second function returns null. I thought that running it only after "DOMContentLoaded" would solve this problem? What am I missing here? (please let me know if I'm not putting enough of my code here to show what I'm trying to do.)
//Add initial invisible quote
(function () {
var quoteList = document.querySelector(".hidden-quotes").children;
var randomQuoteNum = Math.round((Math.random() * (quoteList.length - 1)));
var quoteBox = document.getElementById("quote-box");
quoteBox.innerHTML = quoteList[randomQuoteNum].innerHTML;
var tweetQuote = (quoteBox.children[0].innerHTML + " " + quoteBox.children[1].innerHTML);
var tweetButton = document.getElementById("tweet-button");
tweetButton.setAttribute("data-text", tweetQuote);
tweetButton.setAttribute("data-url", " ");
})();
//Set up quote button functionality
var magicButton = document.getElementById("quote-button");
magicButton.addEventListener("click", function () {
var quoteList = document.querySelector(".hidden-quotes").children;
var randomQuoteNum = Math.round((Math.random() * (quoteList.length - 1)));
var quoteBox = document.getElementById("quote-box");
quoteBox.innerHTML = quoteList[randomQuoteNum].innerHTML;
var tweetQuote = (quoteBox.children[0].innerHTML + " " + quoteBox.children[1].innerHTML);
var tweetButton = document.getElementById("tweet-button");
console.log(tweetButton);
tweetButton.setAttribute("data-text", tweetQuote);
quoteBox.style.opacity = 1;
});
Here's the markup:
<a id="tweet-button" class="twitter-share-button" href="https://twitter.com/intent/tweet">Tweet this.</a>
Only the first function seems to be able to access and modify an attribute of the above element, while the second function cannot even find it (getDocumentById returns null).
And here's the codepen.
It looks like the button you set up with the class twitter-share-button is changed a bit by the script that loads it. Try getting it like this.
var tweetButton = document.getElementsByClassName("twitter-share-button")[0];

Keep Javascript constant the same after function is recalled

I am trying to create a dynamic list so when the user performs a search it will repopulate the list. The problem is that I can't seem to make an immutable constant to store the original div content. Every time the function get's called this variable gets reinitialized.
Is there a way to achieve this without using cookies ? Any help is sincerely appreciated. The code is not complete because I couldn't get passed this step but if you think I am totally heading toward the wrong direction please let me know.
const originalList = document.getElementById('patientList').getElementsByTagName('li');
frozen = Object.freeze(originalList);
<script>
const originalList = document.getElementById('patientList').getElementsByTagName('li');
frozen = Object.freeze(originalList);
var newList = '';
var found = false;
function filterPatients(){
var searchQuery = document.getElementById('search');
var query = searchQuery.value;
var listContainer = document.getElementById('patientList');
var patientList = listContainer.getElementsByTagName('li');
for (var i = 0; i < originalList.length; i++){
var link = patientList[i].getElementsByTagName('a');
var link = link[0].text;
/** remove whitespaces for easy comparison **/
link = link.toLowerCase();
query = query.toLowerCase();
link = link.replace(/\s/g, "");
query = query.replace(/\s/g, "");
/** check every character in query **/
if (link.length > query.length && link.substring(0,query.length) == query){
found = true;
newList += '<li>' + patientList[i].innerHTML + '</li>';
}
}
if (found == true){
listContainer.innerHTML = newList;
newList = '';
}
else{
listContainer.innerHTML = "<li>No patient by that name</li>";
}
console.log(frozen);
}
</script>
const originalList = document.getElementById('patientList').getElementsByTagName('li').cloneNode(true);
Make originalList a copy of the element. Currently, you are setting originalList and patientList to be the same list of elements, so changing one will also change the other. Use element.cloneNode(true) to make a deep copy of a DOM element

Using Javascript to dynamically create dom elements with incrementing ID's

I have a div with an ID "orangeButton" and each time you click on it it creates a new div. This works fine but... I want each newly created div to have an incremental number added to it's ID.
I am not sure how to do this.
Here is a fiddle of the code I have thus far with comments.
http://jsfiddle.net/taoist/yPrab/1/
Thank you
Javascript Code
var applicationArea = document.getElementById("applicationArea");
var orangeButton = document.getElementById("orangeButton");
orangeButton.onclick = function() {
var newDivThingy = document.createElement("div");
newDivThingy.id = 'newDivThingy'; // I want each newly created div to have a numeric value concatenated to it's ID. IE newDivThingy1 newDivThingy2 newDivThingy3
applicationArea.appendChild(newDivThingy);
};​
Am I missing something, why not use a counter?
var counter = 0;
button.onclick = function(){
var newDivThingy = document.createElement("div");
newDivThingy.id = 'newDivThingy' + (++counter);
// continue your stuff here
}
Libraries like underscorejs provide a uniqueid function for this. Otherwise its easy to implement one.
myNamespace.uniqueId = (function () {
var counter = 0; // in closure
return function (prefix) {
counter++;
return (prefix || '') + '-' + counter;
};
}());
Usage.
newDiv.id = myNamespace.uniqueId('newDiv');
Simply use a integer and increment it as each element is added.
var applicationArea = document.getElementById("applicationArea"),
orangeButton = document.getElementById("orangeButton"),
counter = 1;
orangeButton.onclick = function() {
var newDivThingy = document.createElement("div");
newDivThingy.id = "newDivThingy" + counter++;
applicationArea.appendChild(newDivThingy);
}
I have no doubt you have solution and may have forgotten this post.
BUT, I wold like to show a solution that is a compact format.
Note the counter is set to (counter++) so it will start at 1.
var orangeButton = document.getElementById("orangeButton");
var counter = 0;
orangeButton.onclick = function() {
document.getElementById('applicationArea')
.appendChild(document.createElement('div'))
.setAttribute("id", 'newDivThingy' + counter++);
// I want each newly created div to have a
// numeric value concatenated to it's ID.
// IE newDivThingy1 newDivThingy2 newDivThingy3
};​

How can I use an array or another approach to improve since this list will grow?

This code works but will quickly be inefficient (already so?) as my var list grows.
I am adding Twitter streams to pages with their new API. That means I need to provide them some info manually and they return an ID string. That's OK, no workaround.
This example uses the info I need for just three streams but the list will quickly grow to dozens or even more.
function isValidTweets(ts_titletweets) {
var widgetid = $('#TweetStuff').attr('data-widget-id');
var jackID = '243441836335697920'; //IDs associated with streams
var jillID = '243398621595312128';
var harryID = '243398621595312130';
var ts_titletweets = title.toLowerCase(); //title is parsed from URL elsewhere
validtweets = "jack|jill|harry"; // if the title doesn't match then no streams should be used
if (validtweets.indexOf(ts_titletweets.toLowerCase() + "|") > -1) {
console.log('TweetsEnabled');
if (ts_titletweets == "jack")
{widgetid = jackID;
console.log(widgetid + title)}
else if (ts_titletweets == "jill")
{widgetid = jillID;
console.log(widgetid + title)}
else if (ts_titletweets == "harry")
{widgetid = harryID;
console.log(widgetid + title)};
$('#TweetStuff').html("<a class=\"twitter-timeline\" width=\"500\" height=\"600\" data-widget-id=" + widgetid + "></a>");
$("#newTweetsButton").delay(3000).show(0);
$("#filters").css({'margin' : '-30px 0px 0px 0px'});
return true;
} console.log('no Tweets');
return false;
}
I'm certain I'm manually reentering and want to avoid that as the list grows.
Any and all suggestions are much appreciated for a grateful newbie.
Thanks!
UPDATED TYPOS
I would create an object that has properties that correspond to the person's name. You then store the id against that. Next you can check whether it exists and execute your code.
http://jsfiddle.net/7PSNt/1/
var title = 'jill'; //hard coded for demo purposes
var myObject = {
'jack': 1,
'jill': 2,
'harry': 3
};
//I assume title is just one of the keys above (jack, jill, harry)
var ts_titletweets = title.toLowerCase();
//if the object contains a property for the title then we can proceed
var tweetID = myObject[ts_titletweets];
if (tweetID != undefined) {
widgetid = tweetID;
console.log(widgetid + ':' + title)
}
​
Not really sure what you are asking, but here's some stuff that might help:
// define an object with name: id pairs
var twitterIds = {
'jack': '243441836335697920',
'jill': '243398621595312128',
'harry': '243398621595312130'
};
foreach(var name in twitterIds) {
// name = jack
// twitterIds[name] = '243441836335697920'
}
function loadTweets ( name ) {
if( name && twitterIds[name] ) {
// load stream here. Use twitterIds[name] to get the twitter id
}
}
For efficiency, try this:
//cache of static jQuery objects
var $$ = {
'TweetStuff': $('#TweetStuff'),
'newTweetsButton': $("#newTweetsButton"),
'filters': $("#filters")
};
//define the ids in an outer scope - this gives isValidTweets less work to do each time it is called
var ids = {
jack: '243441836335697920',
jill: '243398621595312128',
harry: '243398621595312130'
};
function isValidTweets(title) {
var t = title.toLowerCase();
var widgetid = ids[t] || $$.TweetStuff.attr('data-widget-id');
$$.TweetStuff.html("<a class=\"twitter-timeline\" width=\"500\" height=\"600\" data-widget-id=" + widgetid + "></a>");
$$.newTweetsButton.delay(3000).show(0);
$$.filters.css({'margin' : '-30px 0px 0px 0px'});
console.log('Tweets: ' + (ids[t] ? (widgetid + ' - ' + title) : 'none'));
return !!ids[t];//true or false
}
I'm not sure I understand what's going on in the code, but what you could be using is a lookup-table.
var ids = {
'jack': '243441836335697920',
'jill': '243398621595312128',
'harry': '243398621595312130'
};
if (/*whatever*/) {
widgetid = ids[ts_titletweets];
console.log(widgetid + title);
}

getAllBookmarks in firefox

I'm trying to get the content from all the nodes in the bookmarks menu into textbox.value, but only the last bookmark appears. What am I doing wrong?
function AllBookmarks()
{
var historyService = Components.classes["#mozilla.org/browser/nav-history-service;1"]
.getService(Components.interfaces.nsINavHistoryService);
var options = historyService.getNewQueryOptions();
var query = historyService.getNewQuery();
var bookmarksService = Components.classes["#mozilla.org/browser/nav-bookmarks-service;1"]
.getService(Components.interfaces.nsINavBookmarksService);
//var toolbarFolder = bookmarksService.toolbarFolder;
//var bookmarksMenuFolder = bookmarksService.bookmarksMenuFolder;
var unfiledBookmarksFolder = bookmarksService.unfiledBookmarksFolder;
//query.setFolders([toolbarFolder], 1);
//query.setFolders([bookmarksMenuFolder], 1);
query.setFolders([unfiledBookmarksFolder], 1);
var result = historyService.executeQuery(query, options);
var rootNode = result.root;
rootNode.containerOpen = true;
// iterate over the immediate children of this folder
for (var i = 0; i < rootNode.childCount; i ++) {
var node = rootNode.getChild(i);
}
// close a container after using it!
rootNode.containerOpen = false;
var textbox = document.getElementById("MyExtension");
var title= "Title: " + node.title; // shows the title of URL
var url= "\nURL: " + node.uri; // shows the URL
textbox.value = title + url + "\n";
}
In the loop commented as "iterate over the immediate children of this folder", you are probably looping over each of the bookmarks correctly, but you are not doing anything with the each node before moving on to the next. As a result, the node variable is set to the last node when you leave the loop.
Also, you are assigning to textbox.value, rather than appending to it, so even if you were acting on the data for each node you would have clobbered it each time, resulting in only the data of the last node (the same outcome!). If you want to build up a string like that, you have to append to it, not assign to it. One way to do this is with the += operator.
So, the last part of the code should be something like:
var textbox = document.getElementById("MyExtension");
// iterate over the immediate children of this folder
for (var i = 0; i < rootNode.childCount; i ++) {
var node = rootNode.getChild(i);
var title = "Title: " + node.title; // gets the title of URL
var url = "\nURL: " + node.uri; // gets the URL
textbox.value += title + ": " + url + "\n"; // note the += (append) operator
}
// close a container after using it!
rootNode.containerOpen = false;
NB: In many other (stricter) languages, your posted code wouldn't compile because you're using the variable node outside of the "scope" (the braces) in which it was declared. It is a good rule of thumb to follow voluntarily though: violating this guideline often means you're making a mistake, or need to think more carefully about what you're doing. In this very case, it may have alerted you to the problem.

Categories