0

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>
1

3 Answers 3

1

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/

Sign up to request clarification or add additional context in comments.

Comments

1

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

Comments

1

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.