Displaying all icons in a glyph - javascript

I'm writing a widget UI where the user can manipulate widgets and text. One of the UI functions needed is to select an icon from the list of icons in a glyph and as I'm using twitter bootstrap it should be possible to select the "icon-" classes in the CSS in JavaScript then display them in a DIV. However I'm still relatively new to web development so unsure how I can loop through all the CSS classes selecting all the "icon-" classes. I can see how to do that with a selector to search the HTML body, for example with $.find("[class^='icon-']"); but I'm not sure how to do similar to search the CSS file itself and extract a list of CSS icon classes.
Thanks for any pointers.

Something like this should work if your browser implements the CSSStyleSheet interface:
var icons = [];
var cssRules = document.styleSheets[0].cssRules; // your bootstrap.css
for (var i=0; i<cssRules.length; i++) {
var selectorText = cssRules[i].selectorText;
if (selectorText && selectorText.match(/^\.icon-[a-z_-]+$/)) {
icons.push(selectorText);
}
}
http://jsfiddle.net/V2wjX/

The best approach I can think of is creating an array of the possible values, then looping through them. Here, I made it for you: (from this page)
var icons = ["glass","music","search","envelope","heart","star","star-empty","user","film","th-large","th","th-list","ok","remove","zoom-in","zoom-out","off","signal","cog","trash","home","file","time","road","download-alt","download","upload","inbox","play-circle","repeat","refresh","list-alt","lock","flag","headphones","volume-off","volume-down","volume-up","qrcode","barcode","tag","tags","book","bookmark","print","camera","font","bold","italic","text-height","text-width","align-left","align-center","align-right","align-justify","list","indent-left","indent-right","facetime-video","picture","pencil","map-marker","adjust","tint","edit","share","check","move","step-backward","fast-backward","backward","play","pause","stop","forward","fast-forward","step-forward","eject","chevron-left","chevron-right","plus-sign","minus-sign","remove-sign","ok-sign","question-sign","info-sign","screenshot","remove-circle","ok-circle","ban-circle","arrow-left","arrow-right","arrow-up","arrow-down","share-alt","resize-full","resize-small","plus","minus","asterisk","exclamation-sign","gift","leaf","fire","eye-open","eye-close","warning-sign","plane","calendar","random","comment","magnet","chevron-up","chevron-down","retweet","shopping-cart","folder-close","folder-open","resize-vertical","resize-horizontal","hdd","bullhorn","bell","certificate","thumbs-up","thumbs-down","hand-right","hand-left","hand-up","hand-down","circle-arrow-right","circle-arrow-left","circle-arrow-up","circle-arrow-down","globe","wrench","tasks","filter","briefcase","fullscreen"]
Now you can loop through this array, and create the elements as needed.
for (var i=0,l=icons.length; i<l; i++){
var el = document.createElement('i');
el.className = 'icon-'+icons[i];
document.getElementById("iconContainer").appendChild(el);
}
JSFIDDLE
As for searching the CSS, I can suggest you to write a function like this:
You somehow get the contents of a CSS file into a string, using AJAX (jqXHR) possibly.
Then, write a very basic parsing script, which accepts the CSS string as the parameter.
function getIcons(cssStr){
var matches = cssStr.match(/\.icon\-\w*.*\{/g), icons = [];
for (var i=0,l=matches.length; i<l; i++) icons.push(matches[i].replace(/\.icon\-/g,'').replace(/\W/g,''));
return icons;
}
This will give you the array shown before.
JSFIDDLE

Related

What is a safe alternative to .innerHTML and Jquery .append?

Firefox addon got removed because of unsafe assignment to innerHTML. Replaced it with the Jquery append(), but it is also unsafe. What can I use instead?
I need to add content dynamically to the extension's DOM. Mozilla gave me this link when they took down the addon: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Safely_inserting_external_content_into_a_page
But I can not figure out from the link how to add nodes to an existing node in a safe way.
This is an example of what i'm doing now. I have several places where I append a node to another node. In this case I need to make a div for every category and add it to the node "folders"
var folders = $("#folders");
for (var i = 0; i < categories.length; i++) {
var s = categories[i];
var categoryFolder = $("<div>");
categoryFolder.addClass("folder");
categoryFolder.attr("id",s);
categoryFolder.text(s);
folders.append(categoryFolder);
}

Material Components Web - mdc attachTo only apply to the first element

I'm using Material Components Web to create a website. I have a list of button with the class .mdc-button and I activated it with the following line into my Javascript File.
window.button = new mdc.ripple.MDCRipple.attachTo(document.querySelector('.mdc-button'));
The problem is that this only applies to the first element with the class .mdc-button
Why is that and how to fix it?
document.querySelector will always return the first instance of the element found within the DOM. You can use document.getElementsByClassName('mdc-button') to return a full list of classes within the DOM.
https://www.w3schools.com/jsref/met_document_getelementsbyclassname.asp
Perhaps something like this
var x = document.getElementsByClassName('mdc-button');
var i;
for (i = 0; i < x.length; i++) {
mdc.ripple.MDCRipple.attachTo(x[i]);
}
Here is an ES6 way of doing the same thing (for anyone else reading this post):
const buttons = document.querySelectorAll('.mdc-button');
buttons.forEach(button => MDCRipple.attachTo(button));

Using 'vanilla' JS to set CSS property on selected elements

JavaScript Newbie so the following question maybe 'dumb'.
For my work I do a little GreaseMonkey scripting to make our eCommerce store back end a little more friendly to our customer service team. Normally I'd make a new or better UI for them setup a special role or something, but with this current system, this is literally not an option.
Specifically I make a selection of links visibility: hidden, as they trigger some reporting functions which can lock up the backend till the reports are completed.
Up to this point I have had the script load jQuery, which is fine but not ideal. Then I dug in and saw that the interface was built using YUI, while this is already loaded, the syntax is weird to me, and I don't like it much, plus it is now not supported.
Recently I found the Plain JS site, which describes how to use 'vanilla' JS to do jQuery like things. Splendid! I thought, Now I can just write simple JS without extra dependencies or libs! But this is not quite the case.
I have tried the following:
var links = Array.from(document.querySelectorAll("a")); // creates an actual array from the node list returned by document.query
var links_to_hide = links.slice(14, 22); // gets just the bits we want to affect from the array, and is still an array
// ok so 'links_to_hide' is an array, and it is an array of 'a' anchor tags.
// if I go into the inspector and set the visibility property it affects the tag but doing it via scripting seems to not work.
// so if links_to_hide is an array it should be possible to
for(var i = links_to_hide.length; i <= links_to_hide.length; i++){
links_to_hide.style['visibility'] = 'hidden';
}
// this for loop doesn't seem to actually affect anything
What am I missing. Near as I can tell this should work.
Change this:
for(var i = links_to_hide.length; i <= links_to_hide.length; i++){
links_to_hide.style['visibility'] = 'hidden';
}
To this
for(var i = 0; i < links_to_hide.length; i++){
links_to_hide[i].style['visibility'] = 'hidden';
}
You aren't using i
links_to_hide[i].style.visibility = 'hidden';
Your for loop should be like below:
for(var i = 0; i < links_to_hide.length; i++){
links_to_hide[i].style.visibility = 'hidden';
}

How to change CSS file using JavaScript?

I would ask how to change src of CSS using pure Javascript. I saw on internet that one guy used cookies for this, by i tried sth like this:
window.onload = function onload() {
setTimeout(function(){
document.styleSheets[1].href = "file:///C:/Users/Ma%C5%9Blan/Desktop/Site/bootstrap-3.3.6-dist/project1a.css";
}, 3000);
};
And it didn't work (i want to change CSS after 3 s, i know that actual localization is local, on my PC. Just trying :) ). I want to swap whole file.
Any ideas? If it's impossible in pure JS, show me jQuery way then.
Thanks!
document.styleSheets is a READ-ONLY property, so you won't be able to change the properties of that array.
What you want to do instead is get a list of all the <link> elements in the head, then either use a regex or conditional statement to get the element you are looking to replace, and use .href on that element.
E.G.
// get all links in the head (including CSS)
var allLinks = document.head.getElementsByTagName('link');
// find and replace the element
for (var i = 0; i < allLinks.length; i++) {
if ( allLinks[i].href = "old/url/to/css/file.css") {
allLinks[i].href = "file:///C:/Users/Ma%C5%9Blan/Desktop/Site/bootstrap-3.3.6-dist/project1a.css";
}
}

Remove items from an HTML collection based on another HTML collection

I'm trying to crete 3 HTML collections containing all my links on a page, so I can attach 3 separate function to each categories of links.
My first HTML collection is "header links", the second is "footer links" and the third is "all other links". I need to attach link tracking functions and other elements as well.
Creating the first two collections is fairly easy as I can do document.getElementById('header'); and document.getElementById('footer'); and then this.getElementsByTagName('a');
However, getting the third collection of "all other links" is a bit more tricky. There isn't a clean div that contains just the "middle" of the page, and there are links outside the header and footer that are also difficult to single out.
I wish I could do something like allLinks = document.linnks, and then filter out of that all the links already present in the first and second HTML collections.
Any way to do that ? Ideally I would like to avoid loading more libraries and pure JS would be welcome
Thanks !
You can turn the node lists into arrays, then use filter() to pull out links that are already in one of the other lists:
var hdr = document.getElementById('header');
var hlinks = arrayOf(hdr.getElementsByTagName('a'));
var ftr = document.getElementById('footer');
var flinks = arrayOf(ftr.getElementsByTagName('a'));
var others = arrayOf(document.getElementsByTagName('a')).
filter(
function(element) {
return (hlinks.indexOf(element) < 0) && (flinks.indexOf(element) < 0);
}
);
function arrayOf(nodelist)
{
var result = [];
for ( var i = 0; i < nodelist.length; ++i )
result.push(nodelist.item(i));
return result;
}
Example: http://codepen.io/paulroub/pen/ikebh
If you need to support older browsers that lack Array.prototype.filter(), include the code from this MDN page to implement it when needed.

Categories

Resources