Is there any way to extract css values from website page using css class name. I want to get all css values and child class values using parent class css name.
For an Example:
Wepage Css :
.container {
width: 80%;
}
.btn-wrap {
padding: 3px;
width: 25%;
text-align: center;
}
.text-box {
margin: 0 auto;
width: 50%;
}
.frm-btn-grp {
padding: 3px;
width: 100%;
text-align: center;
.btn-success {
border: 1px solid green;
padding: 7px 24px;
border-radius: 2px;
color: white;
background-color: green;
width: 100px;
}
}
If i will give .frm-btn-grp as input It will return
.frm-btn-grp {
padding: 3px;
width: 100%;
text-align: center;
.btn-success {
border: 1px solid green;
padding: 7px 24px;
border-radius: 2px;
color: white;
background-color: green;
width: 100px;
}
}
Is this possible?
Here's some webscraping action:
import re
import urllib.request as ureq
sample_url = "https://stackoverflow.com/questions/59685137/how-to-extract-css-values-from-website-page"
with ureq.urlopen(sample_url) as req:
data = req.read().decode('utf-8')
#- Split HTML by line ending; Look for 'text/css' matches
css_lines = [i.strip() for i in data.split('\n') if len(i) > 0 and 'text/css' in i]
#-- Create a simple regular expression to extract the css html
#-- Note: ?P<named_tag> allows for naming each section, but I think
#-- it only works on compiled regular expresions, which isn't a huge
#-- deal.
css_pat = r'href="(?P<css_url>.+)"'
p = re.compile(css_pat)
#-- Create a list and append it with our matches.
css_urls = []
for i in css_lines:
tmp = p.search(i).group('css_url')
if tmp:
css_urls.append(tmp)
Output:
In[4]: css_urls
Out[4]:
['https://cdn.sstatic.net/Shared/stacks.css?v=d0797a2dd6f2',
'https://cdn.sstatic.net/Sites/stackoverflow/primary.css?v=f7becef1b212']
Then, you can do whatever. Iterate the urls to get all of the css data, open and join all the css files into one, etc.
with ureq.urlopen(css_urls[0]) as req:
css_data = req.read().decode('utf-8')
#-- Here's a sample printout of a css file for this page
#-- I added some .replace() statments to make it prettier :-)
print(css_data[:500]
.replace(',', ',\n')
.replace('{', ' {\n\t')
.replace(';', ';\n\t')
.replace('}','\n\t}\n\n')
)
Truncated output:
html,
body,
div,
span,
{...}
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
margin:0;
padding:0;
border:0;
font:inherit;
font-size:100%;
vertical-align:baseline
}
article,
a
Related
This is what I have in my .pug file that I need the website to remember. If a user clicks the Large button then the website should remember that when the website is refreshed.
.scaling
scalingButton(onclick='body.style.fontSize = "1.0em"')='Normal'
scalingButton(onclick='body.style.fontSize = "1.2em"')='Medium'
scalingButton(onclick='body.style.fontSize = "1.5em"')='Large'
and here is what I have in the .css file for these buttons:
.scaling{
text-align: end;
position: fixed;
margin: 150px;
margin-right: 0%;
margin-bottom: 5%;
bottom: 0px;
right :20%;
}
scalingButton{
background-color: white;
padding: 5px 10px;
margin-top: 600px;
font-weight: bold;
border-radius: 3px;
border: 2px solid black;
filter: drop-shadow(2px 2px 2px black);
transition: 0.3s;
}
scalingButton:hover{
background-color: grey;
cursor: pointer;
}
You need to write a function that stores value in localStorage and when page is loaded (DOMContentLoaded ) you need to check localStorage, if localStorage has a font-size then you can apply it to the body.
script:
function changeFontSize(size) {
let fontSize = size + "em"
body.style.fontSize = fontSize;
localStorage.setItem('font-size', fontSize);
}
document.addEventListener("DOMContentLoaded", function(event) {
let fontSize = localStorage.getItem('font-size');
if(fontSize) {
body.style.fontSize = fontSize;
}
});
template
.scaling
scalingButton(onclick="changeFontSize('1.0em')")='Normal'
scalingButton(onclick="changeFontSize('1.2em')")='Medium'
scalingButton(onclick="changeFontSize('1.5em')")='Large'
I had a front-end interview a few months ago with the following problem and guideline:
You are given the baseline CSS, HTML, and JS
You are not allowed to directly edit the predefined HTML or CSS
You are allowed to add new CSS classes and use whatever version of jQuery you want or Vanilla JS
Goal 1: When you click the #container, divide the box (which is 400px by 400px) into four equal sized boxes.
Goal 2: When you click one of the boxes that were created in Goal 1, said box also divides into 4 equal sized boxes as well.
My Problem
No matter what I do, the boxes do not divide perfectly. Not sure why inline-block isn't doing it's think, or what I can't append more than one node. Anyone have some expert tips?
var c = document.getElementById("container");
c.addEventListener("click", function(e) {
var node = document.createElement("div");
node.className = "boxxie";
c.appendChild(node);
c.appendChild(node);
c.appendChild(node);
c.appendChild(node);
})
*,
*:before,
*:after {
box-sizing: border-box;
}
#container {
border: 1px solid #2196f3;
width: 400px;
height: 400px;
}
.boxxie {
display: inline-block;
height: 50%;
width: 50%;
outline: 1px solid black;
}
<div id="container"></div>
Here is the jsfiddle
https://jsfiddle.net/drewkiimon/fvx632ab/
Thanks to #wbarton, I was able to get this answer to work without using flexbox. I was adamant without using flexbox since I was pretty confident that it would not need it. Long and behold, there is a solution without it. By using float: left, we can avoid the vertical align, and by creating a for-loop where we re-create a "new" node, we can just append it four times. I also used a class with my div instead of a direct CSS selector on the div.
Thank you for all the help everyone! Case closed.
document.getElementById("container").addEventListener('click', function(e) {
for (var i = 0; i < 4; i ++) {
var node = document.createElement("div");
node.className = "boxxie";
e.target.appendChild(node);
}
})
*,
*:before,
*:after {
box-sizing: border-box;
}
#container {
border: 1px solid #2196f3;
width: 400px;
height: 400px;
}
.boxxie {
outline: 1px solid tomato;
width: 50%;
height: 50%;
float: left;
}
<div id="container"></div>
My solution: https://jsfiddle.net/fvx632ab/106/
Added CSS:
div {
display: flex;
flex-grow: 0;
flex-shrink: 0;
outline: 1px solid #f33;
width: 50%;
flex-wrap: wrap;
}
Flexbox makes this easy for us, by defining some sensible layouts. We set the width of the child to 50%, and also enable wrapping so that we get two rows (since we're going to add four elements).
Then, in my JavaScript:
document.querySelector('body').addEventListener('click', (e) => {
if (!e.target.matches('div')) {
return;
}
for (let i=0; i<=3; i++) {
e.target.appendChild(document.createElement('div'));
}
});
We listen for clicks on the body (because we're going to be adding more divs later), but filter for only the selector we want, which is div. Then, we just add 4 children.
Nothing new from a JS perspective but to answer #drewkiimon "is possible without flex?"
This example uses floats.
document.querySelector('body').addEventListener('click', (e) => {
if (!e.target.matches('div')) {
return;
}
for (let i = 0; i < 4; i++) {
e.target.appendChild(document.createElement('div'));
}
})
*,
*:before,
*:after {
box-sizing: border-box;
}
#container {
border: 1px solid #2196f3;
width: 400px;
height: 400px;
}
/* ---------- */
#container div {
float: left;
width: 50%;
height: 50%;
outline: 1px solid tomato;
background-color: rgba(64, 224, 208, .1);
}
<div id="container"></div>
Here is my solution.
Using e.target allows you to keep drilling down.
vertical-align: top and line-height: 1px; address spacing issues you might find using inline-block per Get rid of space underneath inline-block image
const c = document.getElementById("container");
c.addEventListener("click", e => {
const target = e.target;
for (let i = 0; i < 4; i++) {
const child = document.createElement("div");
target.appendChild(child);
}
});
#container {
width: 400px;
height: 400px;
border: 1px solid blue;
box-sizing: border-box;
}
#container div {
border: 1px solid red;
display: inline-block;
box-sizing: border-box;
width: 50%;
height: 50%;
vertical-align: top;
line-height: 1px;
}
<div id="container"></div>
I'm tying to bind some value inside a Pug.js filter. But that filter works fine the value doesn't bind.
Output Result with the filter
<style>.#{cs_1}{font-family:monospace !important;color:#a1292c !important}.#{cs_1}:hover{background-color:transparent !important;text-decoration:underline !important}.#{cs_2}{position:absolute;font-size:11px;text-transform:none;left:80px;top:12px;border-left:1px solid #ccc;padding-left:6px}.#{cs_3}{white-space:nowrap}</style>
Output Result without the Filter
<style>
.eTWkI {
font-family: monospace !important;
color: #a1292c !important;
}
.eTWkI:hover {
background-color: transparent !important;
text-decoration: underline !important;
}
.Rzorr {
position: absolute;
font-size: 11px;
text-transform: none;
left: 80px;
top: 12px;
border-left: 1px solid #ccc;
padding-left: 6px;
}
.vMvwp {
white-space: nowrap;
}
</style>
Pug.js Code
Note: That :minifycss filter made with uglifycss module
- var length = 5
- var chars = "ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz_-"
- var cs_1 = utils.randomString(length, chars)
- var cs_2 = utils.randomString(length, chars)
- var cs_3 = utils.randomString(length, chars)
style
:minifycss
.#{cs_1} {
font-family: monospace !important;
color: #a1292c !important;
}
.#{cs_1}:hover {
background-color: transparent !important;
text-decoration: underline !important;
}
.#{cs_2} {
position: absolute;
font-size: 11px;
text-transform: none;
left: 80px;
top: 12px;
border-left: 1px solid #ccc;
padding-left: 6px;
}
.#{cs_3} {
white-space: nowrap;
}
So the Filter looks like :
require('pug').filters = {
minifycss: (text, options) => {
if (!text) return;
return uglifycss.processString(text, options);
}
};
It looks like Pug filters are run at compile time, and don't allow for variable/dynamic content. See this GitHub issue for more info. You can export the minifycss function you've written, then require it within Jade (as is done in this related GitHub issue) in order to get your filter code to work. You'd need to export the require function to Pug (locals.require = require in your route), then use it to require the minifycss function from elsewhere.
However, it also appears as though the above issue was fixed in Pug 2.0.0 beta11. Depending on what version of Pug you're using, that may be the cause of the issue.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
This code is an excerpt from a larger project, but I have tried to pull out the relevant material and provide that only.
I have a project, and the part that I need help with is this:
Product codes are generated by users via a series of drop-downs and radio buttons. The one part that will always stay the same is that there is a
(x11)
at the end of each line with a product number, where 11 represents the quantity of the product code, and will also change.
A demo of the relevant code is available at This Fiddle.
My problem is this: the deleteItem() function works when the code is displayed as
ca-fefefsefef (x45)
but not when I tried to change the format to display the quantity as
ca-fjeoisfne Qty. 78
(The difference being in the way the quantity is displayed, not the code itself)
All of the product codes are examples, are not real, and the actual codes will vary in length and content. The quantity of each product code will change as well.
I suppose what I am asking for is a new regex to replace the old one in the deleteitem() function, but this regex needs to work with
Qty. 23
where 23 is the quantity, and will change from code to code.
Basically, the selection of code that I have provided at the fiddle is designed to display each product code and its corresponding quantity in a drop down. The codes are stored in an array, as well as the quantities(in a separate array). The purpose of the deleteitem() function is when the delete button is clicked next to a product code and quantity, it not only deletes the product code and quantity from the drop-down, but it also deletes the corresponding items in the product_codes and quantities arrays. (with the help of the removetextfromarray() function)
Make sure to watch the web console, it will display the arrays before and after the items are deleted. You'll note that when the quantity is displayed as (x99), it works, but if you change it to Qty. 99, it removes the items from the dropdown, but does not remove the corresponding items from their arrays.
So what I need is a new regex to replace the old one (or possibly a new/updated deleteitem() function that will work with the quantity display format as
Qty. 3
instead of
(x3)
and will delete both the items both from the drop down, and delete the two items from their corresponding arrays.
Please keep in mind the following: The product codes in the array, and the quantities in their own array will change, the ones I have provided are examples. There may be more than three, and they will change in length. I am also unable to use Jquery.
If you can spare the time, I would love any help you can give. I've spent literally hours trying to build new regexes that will work, trying to uncode the existing one (I didn't write it) and such. A working fiddle would be absolutely GREAT. Thanks so much for any help.
If I'm not being clear, please comment and I'll be happy to answer any questions about it or make updates. Thanks again!
How about this: /\w*Qty\. \d+$/
(see example here https://jsfiddle.net/xes3eLxp/1/)
That means, match:
Zero or more white space characters (\w*),
Qty. (Qty\.),
A single space (),
One or more digits (\d+),
The end of the line ($).
Consider the sample string: "ckj-fjeieofj Qty. 56"
The above regex would match Qty. 56
product_codes = ['cr-rttrnhuj3', 'ckj-fjeieofj', 'jjff-cr-sd'];
quantities = ['2', '56', '98'];
myfunction = function () {
document.getElementById('cart_body').innerHTML = '';
cart_text = '';
emp = '<div class="close_button" onclick="deleteItem(this)">x</div>';
open_span = '<span class="close_span">';
close_span = '</span>';
elf = '<br class="none"/>';
for (i = 0; i < product_codes.length; i++) {
cart_text += "<div>" + open_span + product_codes[i] + " Qty. " + quantities[i] + close_span + emp + elf + "</div>";
}
document.getElementById('cart_body').innerHTML = cart_text;
}
function removeTextFromArray(array, text){
for (var i=array.length-1; i>=0; i--) {
if (array[i] === text) {
array.splice(i, 1);
quantities.splice(i, 1);
return array;
}
}
}
myfunction();
hider2 = function () {
cart_bod = document.getElementById('cart_body');
cart_bod.classList.toggle('closed');
}
//below function is the important one
deleteItem = function (item) {
//dot instead of hashtag
item.parentElement.remove();
console.log('set');
var textInNode = item.parentElement.getElementsByClassName("close_span")[0].innerHTML;
textInNode = textInNode.replace(/\w*Qty\. \d+$/g, "").trim();
//new regex is /*\Qty[^)]*\ */g
//old is / *\([^)]*\) */g
codes = removeTextFromArray(product_codes, textInNode);
console.log(product_codes)
console.log(quantities);
}
body {
font: 12px tahoma;
}
.centered {
border: 2px solid transparent;
margin: 0 auto;
width: 90%;
margin-bottom: 10px;
}
#debug-box {
}
#configurator-container {
}
#submit-box {
width: 400px;
height: 50px;
margin-bottom: 5px;
}
#unit-container {
border: 2px solid transparent;
width: 50%;
/*change this width to test whether it'll fit in the SEI website'*/
}
#quantity {
width: 40px;
}
.select-label {
}
dt {
float: left;
width: 45%;
text-align: right;
cursor: default;
}
br {
margin-bottom: 30px;
}
.none {
margin-bottom: 0px;
}
.s_container {
margin-top: 20px;
}
.sm_it {
font-style: italic;
}
i {
padding-left: 20px;
font-size: 10px;
}
input[type='email'] {
width: 235px;
}
.second_line_italics {
padding-left: 40px;
}
#configurator-container {
background-image: url("data:image/gif;base64,R0lGODlhBgAGAKIAANbXy+Hi29rc08THu9HWy8zQwwAAAAAAACH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4wLWMwNjAgNjEuMTM0Nzc3LCAyMDEwLzAyLzEyLTE3OjMyOjAwICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ4bXAuZGlkOkYzM0I5RTQ3Q0UwRUUwMTFCMzMzRkRGNDFGODlGRDVEIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkY2QjNGNjE4ODQ5ODExRTA4MUU4OTkzQzdFOTQ5MDU5IiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkY2QjNGNjE3ODQ5ODExRTA4MUU4OTkzQzdFOTQ5MDU5IiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzQgV2luZG93cyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjcyMDlGMEYwQjg2QUUwMTFCOTg2OTk5N0I0QjM1NDEyIiBzdFJlZjpkb2N1bWVudElEPSIxNzA3NiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgH//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh5N/e3dzb2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vLu6ubi3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZmJeWlZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1dHNycXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1JRUE9OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy4tLCsqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MCwoJCAcGBQQDAgEAACH5BAAAAAAALAAAAAAGAAYAAAMQSBpcLnBIQFlQBApXKJBDAgA7");
}
select {
width: 235px;
}
input[type='number'] {
width: 235px;
}
.twin_btns {
display: inline;
cursor: pointer;
}
.twin_divs {
margin: 0 auto;
margin-top: 10px;
z-index: 300;
position relative;
text-align: center;
}
#second_line_ex-length {
width: 215px;
margin-left: 20px;
}
#b-length-1 {
width: 145px;
}
#b-length-2 {
width: 145px;
}
.hidden {
color: grey;
pointer-events: none;
pointer: default;
border-color: grey;
}
.contact-i-header {
font-weight: bold;
font-size: 18px;
}
input[type='text'] {
width: 235;
}
#request-quote-container {
height: 60px;
width: 90%;
margin:0 auto;
border-bottom: 1px solid #ADAEA9;
font-family: Tahoma;
background-color: #DADCD3;
}
h2 {
opacity: .8;
width: 284.917px;
text-align: right;
}
.side-by-side {
display: inline-block;
}
h5 {
margin-left: 40px;
}
#item {
margin-top: 5px;
}
#triangle-up {
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid black;
opacity: 0.6;
}
.slider {
overflow-y: hidden;
transition-property: all;
transition-duration: 5s;
transition-timing-function: cubic-bezier(0, 1, 0.5, 1);
}
.slider.closed {
max-height: 0;
}
.slider2 {
overflow-y: hidden;
transition-property: all;
transition-duration:.5s;
transition-timing-function: cubic-bezier(0, 1, 0.5, 1);
max-height: 200px;
}
.slider2.closed {
max-height: 0;
}
#submit_info {
text-align: center;
margin: 0 auto;
}
.bottom_btns {
}
#sent_box {
height: 20px;
text-align: center;
}
#write_box {
height: 20px;
text-align: center;
}
#send_box {
height: 20px;
text-align: center;
}
.cart_parts {
border: 1px solid black;
box-sizing: border-box;
width: 60%;
margin: 0 auto;
}
#cart_top {
height: 40px;
font-family: Tahoma;
background-color: #DADCD3;
margin: 0 auto;
box-shadow:
}
#cart_body {
text-align: center;
}
.close_button {
border: 1px solid black;
width: 12px;
height: 12px;
border-radius: 90px;
font-size: 12px;
text-align: center;
line-height: 11px;
background-color: lightGrey;
display: inline-block;
margin-left: 20px;
}
.close_span {
display: inline-block;
}
.close_button:hover {
color: red;
border: 2px solid red;
font-weight: bold;
}
#script_no {
color: red;
text-align: center;
font-size: 16px;
}
#not_supported {
text-align: center;
color: red;
}
#ter {
margin-bottom: 30px;
background-color: red;
}
#submit-box {
margin: 45px auto;
}
#tbr {
margin-bottom:10px;
}
<div id='cart_top' class='cart_parts'> <dt class='list-item' style='margin-top: 10px;'>
View your Quote
</dt>
<dd class='list-item'>
<div id='triangle-up' class='side-by-side' style='float: right; margin-right: 20px; cursor: pointer; margin-top: 15px;' onClick='hider2()'></div>
</dd>
</div>
<div id='cart_body' class='cart_parts slider2 closed'></div>
I want to make sth like this:
http://codepen.io/lukejacksonn/pen/PwmwWV?editors=001
in my site, but I'm using an AngularJS.
The main problem is the JS script. It's jQuery and my problem is: will it work with AngularJS? And if yes - how to properly write this code in Controller (or Directive? - is it a DOM manipulation?)
Code from Codepen:
JS:
var $nav = $('.greedy-nav');
var $btn = $('.greedy-nav button');
var $vlinks = $('.greedy-nav .visible-links');
var $hlinks = $('.greedy-nav .hidden-links');
var breaks = [];
function updateNav() {
var availableSpace = $btn.hasClass('hidden') ? $nav.width() : $nav.width() - $btn.width() - 30;
// The visible list is overflowing the nav
if($vlinks.width() > availableSpace) {
// Record the width of the list
breaks.push($vlinks.width());
// Move item to the hidden list
$vlinks.children().last().prependTo($hlinks);
// Show the dropdown btn
if($btn.hasClass('hidden')) {
$btn.removeClass('hidden');
}
// The visible list is not overflowing
} else {
// There is space for another item in the nav
if(availableSpace > breaks[breaks.length-1]) {
// Move the item to the visible list
$hlinks.children().first().appendTo($vlinks);
breaks.pop();
}
// Hide the dropdown btn if hidden list is empty
if(breaks.length < 1) {
$btn.addClass('hidden');
$hlinks.addClass('hidden');
}
}
// Keep counter updated
$btn.attr("count", breaks.length);
// Recur if the visible list is still overflowing the nav
if($vlinks.width() > availableSpace) {
updateNav();
}
}
// Window listeners
$(window).resize(function() {
updateNav();
});
$btn.on('click', function() {
$hlinks.toggleClass('hidden');
});
updateNav();
LESS:
#color-1: #ff9800;
#color-2: #f57c00;
#color-3: #ef6c00;
body {
min-width: 320px;
padding: 30px;
background: #ff9800;
font-family: Helvetica, sans-serif;
}
h1 {
color: #fff;
font-weight: bold;
text-align: center;
margin-top: 50px;
font-size: 24px;
}
p {
color: #fff;
text-align: center;
margin-top: 10px;
font-size: 14px;
}
a {
color: #fff;
}
.greedy-nav {
position: relative;
min-width: 250px;
background: #fff;
a {
display: block;
padding: 20px 30px;
background: #fff;
font-size: 18px;
color: #color-1;
text-decoration: none;
&:hover {
color: #color-3;
}
}
button {
position: absolute;
height: 100%;
right: 0;
padding: 0 15px;
border: 0;
outline: none;
background-color: #color-2;
color: #fff;
cursor: pointer;
&:hover {
background-color: #color-3;
}
&::after {
content: attr(count);
position: absolute;
width: 30px;
height: 30px;
left: -16px;
top: 12px;
text-align: center;
background-color: #color-3;
color: #fff;
font-size: 14px;
line-height: 28px;
border-radius: 50%;
border: 3px solid #fff;
font-weight: bold;
}
&:hover::after {
transform: scale(1.075);
}
}
.hamburger {
position: relative;
width: 32px;
height: 4px;
background: #fff;
margin: auto;
&:before,
&:after {
content: '';
position: absolute;
left: 0;
width: 32px;
height: 4px;
background: #fff;
}
&:before {
top: -8px;
}
&:after {
bottom: -8px;
}
}
.visible-links {
display: inline-table;
li {
display: table-cell;
border-left: 1px solid #color-1;
}
}
.hidden-links {
position: absolute;
right: 0px;
top: 100%;
li {
display: block;
border-top: 1px solid #color-2;
}
}
.visible-links li:first-child {
font-weight: bold;
a { color: #color-1 !important; }
}
.hidden {
visibility: hidden;
}
}
HTML:
<nav class='greedy-nav'>
<button><div class="hamburger"></div></button>
<ul class='visible-links'>
<li><a target="_blank" href='https://github.com/lukejacksonn/GreedyNav'>Greedy</a></li>
<li><a href='#'>navigation</a></li>
<li><a href='#'>that</a></li>
<li><a href='#'>handles</a></li>
<li><a href='#'>overflowing</a></li>
<li><a href='#'>menu</a></li>
<li><a href='#'>elements</a></li>
<li><a href='#'>effortlessly</a></li>
</ul>
<ul class='hidden-links hidden'></ul>
</nav>
<h1>resize the window</h1>
<p>(animations with <a target="_blank" href="http://codepen.io/lukejacksonn/pen/gpOrmd">actuate</a> coming soon)</p>
will it work with AngularJS?
jQuery will work with AngularJS. It doesn't care if you use/not use AngularJS.
Likewise AngularJS feels the same way about jQuery.
For jQuery to work - It only requires a jQuery object to perform the manipulations.
For AngularJS to work - It expects the angular related properties to be intact, and not be removed by external factors like jQuery.
So will jQuery work with AngularJS - Yes.
Should you use jQuery with AngularJS - No.
And if yes - how to properly write this code in Controller (or Directive? - is it a DOM manipulation?)
Write a Directive - call it the greedy-nav-menu/greedyNavMenu or whatever you like. Pass as an attribute the menu items in an object and let the directive take care of the behavior.
I've conveniently asked you avoid jQuery and "Write a directive" that performs DOM manipulation without jQuery.
Here is what you need to perform DOM manipulation
https://docs.angularjs.org/api/ng/function/angular.element
Also to get the input for angular element - use JavaScript's document.getElementBy*
You get a subset of the jQuery library in the jqLite package - available for you to use through angular element.
If you are not satisfied with the functions in jqLite - go ahead and add jQuery but make sure they're included in the digest loop using angular applyand that you only use the jQuery inside the directive.
For further reading - http://ng-learn.org/2014/01/Dom-Manipulations/
If you also add JQuery to your page this will work fine. You could paste the code into a controller and insert add it to the HTML:
<div ng-controller="NavController">
<nav class='greedy-nav'>
...
</div>
Writing a custom directive is possible and recommended, but will be more complicated.
Also note that angular supports a subset of JQuery alreay, more on this here: https://docs.angularjs.org/api/ng/function/angular.element
You need to rewrite the jQuery code to Angular style. Say, use directive.
Although not recommended, you can simply move the jQuery code to a controller/directive. Angular provides jqLite, which is a subset of jQuery. If you load jQuery before Angular, then jqLite === jQuery.