I'm working on a project that need to allow users to add/remove tags on images.
There is grid view, single view and mixed view. The grid view displays image thumbs in a grid, Single view displays images one by one and the mixed view has the grid in the background, and a single images in the front (a zoom in feature).
All those views have a footer which contains the tags that can be applied to an image. However, the grid has its own footer, while the single and mixed views share theirs.
Here is the HTML side code for those :
<section id="noRefContainer" class="photosWrapper photosWrapper-cq" style="display: block"> <!--ng-controller="gridController">-->
<div class="images-cq__wrapper" ng-show="displayStyle.style == 'grid' || displayStyle.style == 'both'">
<div class="images-cq__item" ng-repeat="photo in displayedPhotos">
<div ng-class="{active: photo.selected}">
<label for="{{photo.uuid}}">
<div class="img-cq">
<img ng-src="{{photo.thumbPath100}}" alt="Alternate Text" ng-click="selectionEvent({value: photo.uuid, event: $event, index: $index})" />
<a href="#" class="zoom-cq" title="zoom" ng-click="zoomOpen({value: $index})">zoom</a>
</div>
<p>
{{photo.title}}
</p>
</label>
</div>
</div>
<div class="images-cq__footer open">
<p>
<span>Tagger les</span>
<strong>{{selectedPhotos.length}}</strong>
<span>éléments sélectionnés</span>
</p>
<div class="images-cq__dropdown top">
<a href="#">...</a>
<ul>
<li><a href="#" ng-click="selectAll()">Sélectionner toutes les images</a></li>
<li><a href="#" ng-click="deselectAll()">Désélectionner toutes les images</a></li>
</ul>
</div>
<div class="images-cq__tags">
<ul>
<li ng-repeat="tag in tags">
<a href="#" ng-class="{'active': tag.status == 'active', 'selected': tag.status == 'selected'}" ng-click="tagSelectionEvent({value : tag.value})">{{tag.name}}</a>
</li>
</ul>
</div>
<small>Attention, ceci effacera les précédents tags.</small>
</div>
</div>
<div ng-class="{'images-cq__lightbox': displayStyle.style == 'both', 'images-cq__wrapper': displayStyle.style == 'single', single: displayStyle.style == 'single'}" ng-show="displayStyle.style == 'both' || displayStyle.style == 'single'">
<div class="images-cq__carousel">
<a href="" class="images-cq__carouselclose" ng-click="zoomClose()" ng-show="displayStyle.style == 'both'">
Close
</a>
<div class="images-cq__carouselcontent" id="carousel">
</div>
<div class="images-cq__carouselfooter">
<div class="images-cq__tags">
<ul>
<li ng-repeat="tag in tags">
<a href="#" ng-class="{'active': tag.status == 'active', 'selected': tag.status == 'selected'}" ng-click="zoomTagSelectionEvent({value : tag.value})">{{tag.name}}</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</section>
And the app.js side code :
$scope.tags = [];
$scope.tags = [{ name: 'CQ:OK', count: 0, status: '', value: 'CQ:OK' },
{ name: 'CQ:OK_NO_ZOOM', count: 0, status: '', value: 'CQ:OK_NO_ZOOM' },
{ name: 'CQ:KO', count: 0, status: '', value: 'CQ:KO' },
{ name: 'Chromie', count: 0, status: '', value: 'Chromie' },
{ name: 'Détourer', count: 0, status: '', value: 'Détourer' },
{ name: 'Nettoyer_redresser', count: 0, status: '', value: 'Nettoyer_redresser' },
{ name: 'Interne', count: 0, status: '', value: 'Interne' },
{ name: 'Otsc', count: 0, status: '', value: 'Otsc' }];
$scope.zoomTagSelectionEvent = function (tag) {
var photo = $scope.carousel.settings.images[$scope.carousel.settings.currentImage];
if ($scope.hasTag(photo, tag.value)) {
$scope.removeTag(photo, tag.value);
}
else {
$scope.addTag(photo, tag.value);
}
$scope.updateTagStatus(tag.value);
}
$scope.tagSelectionEvent = function (tag) {
if ($scope.allHaveTag($scope.selectedPhotos, tag.value)) {
$scope.allRemoveTag($scope.selectedPhotos, tag.value);
}
else {
$scope.allAddTag($scope.selectedPhotos, tag.value);
}
$scope.updateTagStatus(tag.value);
}
$scope.updateAllTagStatus = function () {
angular.forEach($scope.tags, function (value, key) {
$scope.updateTagStatus(value.value);
});
}
$scope.updateTagStatus = function (tag) {
var currentTag = $scope.getTag(tag);
if ($scope.displayStyle.style == 'grid')
{
var tagged = $scope.countTagged($scope.selectedPhotos, tag);
if (tagged == 0) {
currentTag.status = 'none';
}
else if (tagged < $scope.selectedPhotos.length) {
currentTag.status = 'selected';
}
else {
currentTag.status = 'active';
}
}
else {
if ($scope.carousel.settings.currentImage !== false)
{
var photo = $scope.carousel.settings.images[$scope.carousel.settings.currentImage];
var res = $scope.hasTag(photo, tag);
if (res) {
currentTag.status = 'active';
}
else {
currentTag.status = 'none';
}
}
}
console.log('tag ' + tag + ' status updated');
}
Each time a tag is applied to an image, the tag status is updated, which should update the ng-class expression result. The only part that gets properly updated is the grid footer. That is shared between single/mixed view updates only when the view is shown.
As for what i tried to fix this, I've tried using $scope.apply() after each call for tag update, tried placing at the end of the updateTagStatus function. I also tried changing the expressions (class names with/without quotes, setting class to the tag status...), which all worked only for the grid footer, but not for the other. I also checked that the statuses were properly updated, the only problem is in the updating of the display.
Please help.
Update :
I am sorry for not answering in here, there was a huge list of evolutions for the project in a short amount of time so the code causing this problem is no more, which also removes the problem altogether. I was busy working on the project and forgot to update this.
However, thank you for taking the time to come here and try to help me.
I am not sure what i should do in a situation such a this.