Angular access to bound element - javascript

It may be an issue in the way i'm architecting my application, but i keep running into the need to be able to access the dom element via my items array:
$scope.items = [{"src": src, "url": url, "title": title, "top": 0, "left": -500 }];
Bound to html with:
<div class="block" ty-stacked-block ng-repeat="item in items" ng-style="{ 'top' : item.top+'px', 'left' : item.left+'px' }">
<a href="{{ item.url }}" title="{{ item.title }}">
<img ng-src="{{ item.src }}" alt="{{ item.title }}" />
</a>
<br />
<p>{{ item.title }}</p>
</div>
Basically I have another piece of code that wants to run through $scope.items and make changes to the div's positioning (based on each div's height).
scope.repositionItems = function() {
_.each(scope.items, function(item) {
// TODO get item's height somehow
});
};

I added an id to the div "item-{{ $index }}", so i could fetch it by id from my loop. Doesn't feel very "angular", but it worked!
<div id="item-{{ $index }}" class="block" ty-stacked-block ng-repeat="item in items" ng-style="{ 'top' : item.top+'px', 'left' : item.left+'px' }">
<a href="{{ item.url }}" title="{{ item.title }}">
<img ng-src="{{ item.src }}" alt="{{ item.title }}" />
</a>
<br />
<p>{{ item.title }}</p>
</div>

I am not sure why you have layout attributes in your items list, hopefully you don't have a good reason and this will help. If your intention is to have several element blocks stacked on top of each other each containing a result from items then you should let angular repeat the items and not position them at all yourself. Your style attributes in class='block' should create the desired spacing and layout. I have wrapped your code in a unordered list and changed the div tag to an li tag. You can always retain the div inside the li tag. If you don't want to wrap with a ul then apply float:left in class="block"
<ul>
<li class="block" ng-repeat="item in items">
<a href="{{ item.url }}" title="{{ item.title }}">
<img ng-src="{{ item.src }}" alt="{{ item.title }}" />
</a>
<br />
<p>{{ item.title }}</p>
</li>
</ul>
.block {
background-color:#fff;
width:400px;
padding:10px;
border-radius:8px;
margin:10px;
position: relative;
}

Related

Lazysizes.min.js implementation not working

We're attempting to implement (https://github.com/aFarkas/lazysizes/tree/master) on https://berkshireblanket.com.
But after following all directions, the implementation will not work. When I run a check using DevTools, it outputs as false:
typeof($("img").lazyload) === "function"
I'm at a loss, and I'm not sure if we're missing something either within the script or within the HTML.
Here's a look at our HTML to show how it's currently being implemented:
<div class="product-main-images {% if section.settings.thumbnails == 'bottom' %}desktop-12{% else %}desktop-10{% endif %} tablet-6 mobile-3" tabindex="0">
<div class="product-image-container" style="padding-bottom: {{ product_image_box_ratio_max }};" >
{% for image in product.images %}
{% assign image_box_ratio = image.height | append: ".0" | times: 1 | divided_by: image.width | times: 100 | append: "%" %}
{% assign img_url = image | img_url: '1x1' | replace: '_1x1.', '_{width}x.' %}
<div class="product-main-image {% if forloop.first %}selected{% endif %}" data-image-id="{{ image.id }}">
<a class="product-fancybox" rel="product-images" href="{{ image | img_url: '2400x' }}" tabindex="-1">
<img id="{{ product.id }}" class="product__image lazyload"
src="{{ image | product_img_url: '300x' }}"
data-src="{{ img_url }}"
data-sizes="auto"
data-zoom-src="{{ image | img_url: '2400x' }}"
alt="{{ image.alt | escape }}">
</a>
<noscript>
<img id="{{ product.id }}" class="product-main-image lazyload" src="{{ featured_image | product_img_url: '800x' }}" alt='{{ image.alt | escape }}'/>
</noscript>
</div>
{% endfor %}
</div>
</div>
I'd appreciate any help!
Please let me know if I can clarify anything, or provide further examples of our current implementation.
Thanks!
You might need to change src to data-src:
<img id="{{ product.id }}" class="product-main-image lazyload" data-src="{{ featured_image | product_img_url: '800x' }}" alt='{{ image.alt | escape }}'/>
install lazysizes, then add class "lazyload" to all images and iframes and in the img tag make sure to change "src" to "data-src"

AngularJs not showing image from list items

I have a simple list defined in angular:
defaultPointer.list=[
{name:'Scott',age:29,img:'http://localhost/learn/angular/img/1.jpg'},
{name:'Steve',age:19,img:'http://localhost/learn/angular/img/2.jpg'},
{name:'Ben',age:39,img:'http://localhost/learn/angular/img/3.jpg'},
{name:'Penny',age:12,img:'http://localhost/learn/angular/img/4.jpg'}
];
Following is the HTML:
<li ng-repeat="x in defaultPointer.list | filter:defaultPointer.search">
<img ng-src="{{ x.img }}"/> <span>{{x.name | uppercase}} is {{ x.age }}</span>
</li>
For some reason, it's showing empty space and no errors in console. What could be the problem?
Please use my code and check it:
defaultPointer.list=[
{name:'Scott',age:29,img:'img/1.jpg'},
{name:'Steve',age:19,img:'img/2.jpg'},
{name:'Ben',age:39,img:'img/3.jpg'},
{name:'Penny',age:12,img:'img/4.jpg'}
];
Following is the HTML:
<li ng-repeat="x in defaultPointer.list | filter:defaultPointer.search">
<img ng-src="{{ x.img }}"/> <span>{{x.name | uppercase}} is {{ x.age }}</span>
</li>
You have to place this html file in angular folder.

putting jekyll tags in an "onclick" breaks

in jekyll, this works:
---
layout: default
---
<div class="brief">
<ul>
{% for post in site.posts %}
<li class="postlist">
<a href="#" onclick='document.getElementById("one").innerHTML="{{post.url}}";'>{{post.title}}</a>
<p>{{post.meta}} <br>{{post.date}} <br>{{post.category}}</p>
</li>
{% endfor %}
</ul>
</div>
<div class="post" id="one"></div>
but when i change line #8 to:
<a href="#" onclick='document.getElementById("one").innerHTML="{{post.content}}";'>{{post.title}}</a>
it breaks. why does this happen and what can i do to change this and get the desired outcome?
It's likely that your post content is creating invalid HTML (e.g. ending the onclick quotes).
In my opinion, a better method to achieve this would be to render all the post content hidden, and have your onclick toggle a class to display the relevant content. This would save you from the untold horrors of encoding and decoding that content through an attribute value.
For example:
{% for post in site.posts %}
<li>
<a href="#" onclick='document.getElementById("post-content-{{ forloop.index }}").classList.toggle("hidden")'>{{ post.title }}</a>
<p>{{ post.meta }} <br>{{ post.date }} <br>{{ post.category }}</p>
<p id="post-content-{{ forloop.index }}" class="hidden">{{ post.content }}</p>
</li>
{% endfor %}
External CSS:
.hidden {
display: none;
}
You could also extend this to hide all content sections first, so only one is shown at a time.

Calling a method individually by class selector

In my blog I'm using Pico CMS, in the index.twig page I wrote this code that generates HTML with page title, description, and URL:
{% for page in pages|sort_by("time") %}
{% if page.id starts with "blog/" %}
<div class="post">
<h3>
<a class="page-title" href="{{ page.url }}">{{ page.title }}</a>
<small class="date">{{ page.date }}</small>
</h3>
<p class="excerpt">{{ page.description }}</p>
{% endif %}
{% endfor %}
My idea was to make each title in a different color, I used randomColor, and wrote this JavaScript:
$('.page-title').css('color', randomColor() );
But this makes all the page-titles in the page to be of same color, I would like each of them in a different color.
This is the website: blog.lfoscari.com
$('.page-title').css('color', randomColor() ); in plain english is Call the function randomColor() and get the colour and then set the same to all the elements matching the class.
You've to use each() to iterate over all elements, get the random colour by calling the function and set it to each element individually.
$('.page-title').each(function() {
$(this).css('color', randomColor())
});
You can use css() with callback , it will iterate over elements and you can update value by returning
$('.page-title').css("color", randomColor);
<script src="https://cdnjs.cloudflare.com/ajax/libs/randomcolor/0.4.4/randomColor.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="page-title">1</div>
<div class="page-title">1</div>
<div class="page-title">1</div>
<div class="page-title">1</div>
<div class="page-title">1</div>
<div class="page-title">1</div>
Twig has a random function that you can use:
<a class="page-title"
style="color: {{ random(['orange', 'pink', 'LightSkyBlue']) }}"
href="{{ page.url }}">{{ page.title }}</a>

Creating filters dynamically with ng-click and ng-repeat

Right now, I have a bunch of filters that use ng-click to filter some JSON data pulled in from a factory:
<ul class="brands">
<li><a href="#" ng-click="brandFilter = null">All</li>
<li>Apple</li>
<li>Samsung</li>
<li>HTC</li>
</ul>
<div ng-controller="phonesController">
<div class="phonesContent">
<article ng-repeat="phones in phoneData | filter:brandFilter" class="phone-article">
<img src="{{ phones.image }}" alt="{{ phones.name }}" class="phone-img">
<p>{{ phones.name }}</p>
<p>Price: ${{ phones.price }}</p>
<p>No term: ${{ phones.no-term }}</p>
</article>
</div>
</div>
It works well, but I'm wondering how I can programmatically generate the links and use ng-click to filter. My best attempt so far:
<div ng-controller="phonesController">
<ul class="brands">
<li><a href="#" ng-click="brandFilter = null">All</li>
<li ng-repeat="phones in phoneData | unique: 'manufacturer'">{{ phones.manufacturer }}</li>
</ul>
<div class="phonesContent">
<article ng-repeat="phones in phoneData | filter:brandFilter" class="phone-article">
<img src="{{ phones.image }}" alt="{{ phones.name }}" class="phone-img">
<p>{{ phones.name }}</p>
<p>Price: ${{ phones.price }}</p>
<p>No term: ${{ phones.no-term }}</p>
</article>
</div>
</div>
The links are generating properly and the data is showing up in the phonesContent div, but the filtering is not working. I keep getting a $parse:syntax error so something is wrong with my expression where brandFilter = { 'manufacturer' = phones.manufacturer } (I think).
Rob has pointed out why your code is not working, but I would say it's best to avoid having assignment statements in your directives. That way the interface to your controler is clearly defined.
I'd suggest adding a scope function setFilter() to your controller that sets the filter value:
$scope.setFilter = function (value) {
$scope.brandFilter = value ? { manufacturer: value } : null;
};
Then you can do this:
<li><a href="#" ng-click="setFilter(null)">All</li>
<li ng-repeat="phones in phoneData | unique: 'manufacturer'">
{{ phones.manufacturer }}
</li>

Categories

Resources