Vue: Show/Hide image based on its own src attribute - javascript

Is there a way to reference the current element in a vue template? I tried using this but that doesn't seem to work.
Basically I only want to show the img tag if the source attribute has a length greater than zero which changes from the selection of the bootstrap dropdown that it is within.
<img id="active_item_icon" v-show="this.src.length > 0 || !!data.icon_url" :src="data.icon_url" alt="Item Icon">
Full Code:
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" style="width:100%;text-align:left;" type="button" id="dropdown-item-icon-url" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<!-- This is the image that I want to watch -->
<img id="active_item_icon" v-show="this.src.length > 0 || !!data.icon_url" :src="data.icon_url" alt="Item Icon">
<span v-show="!data.icon_url">No Icon Selected</span>
</button>
<ul class="dropdown-menu" style="width:100%" aria-labelledby="dropdown-item-icon-url">
<li v-on:click="updateURL" v-for="item in $store.state.icons" :key="item.id">
<img :src="$store.getters.icon(item.id)" alt="">
</li>
</ul>
<input type="hidden" name="icon_url" id="item_icon_url" :value="data.icon_url || ''">
</div>

If you can access data.icon_url for the img tags source and it is a string, you could do a v-if on that, and remove the or.
<img id="active_item_icon" v-show="data.icon_url.length > 0" :src="data.icon_url" alt="Item Icon">

Not sure why I didn't think of this, but I just need to bind it to some data:
export default {
data: () => ({
showUrl: ''
}),
methods: {
updateURL(e) {
this.showUrl = e.currentTarget.querySelector('img').src
},
}
}
<img id="active_item_icon" v-show="!!showUrl.length" :src="showUrl" alt="Item Icon">

Related

I want to show only one input clicked (on vue.js)

I would like to show an input on the click, but being in a for loop I would like to show only the clicked one
<div v-for="(todo, n) in todos">
<i class="fas fa-minus ml-2"></i>
<li class="mt-2 todo">
{{ todo }}
</li>
<li class="button-container">
<button class="ml-1 btn btn-primary rounded-circle btn-sm" v-if="isHidden" v-on:click="isHidden = false"><i
class="THIS-CLICK"></i></button>
<input class="ml-5 border border-primary rounded" v-if="!isHidden" v-model="todo">
<button class="ml-1 btn btn-success rounded-circle btn-sm" v-if="!isHidden" v-on:click="isHidden = true"
#click="modifyTodo(n, todo)"><i class="far fa-save"></i></button>
</li>
</div>
I would like that on clicking on THIS-CLICK, only one input (that of the button clicked) is visible, but being in a for loop I don't know if it can be done
I would suggest to change the structure a bit in your app. You can clean up your code a lot by using v-if inside the button instead of two different buttons.
Also, moving as much javascript out from the markup as possible is a good practice.
I have an example below where this is done.
Regarding your question, you would have to add the key to each todo item.
new Vue({
el: "#app",
data() {
return {
todos: [{
name: 'wash hands',
isHidden: true
},
{
name: 'Stay home',
isHidden: true
}
],
};
},
methods: {
toggleTodo(n, todo) {
const hidden = todo.isHidden;
if (hidden) {
this.modifyTodo(n, todo);
todo.isHidden = false;
} else {
todo.isHidden = true;
}
},
modifyTodo(n, todo) {
//Some logic...
}
},
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="app">
<div v-for="(todo, n) in todos">
<i class="fas fa-minus ml-2"></i>
<li class="mt-2 todo">
{{ todo.name }}
</li>
<li class="button-container">
<input class="ml-5 border border-primary rounded" v-if="!todo.isHidden" v-model="todo.name">
<button #click="toggleTodo(n, todo)">
<i v-if="todo.isHidden" class="THIS-CLICK">click-this</i>
<i v-else class="far fa-save">save</i>
</button>
</li>
</div>
</div>
If you cannot do this, you could go with adding a new key to data like: hiddenTodos that would be an array of ids/a unique identifier to the todo you selected to hide.
in the template, it would be something like this:
<button #click="hiddenTodos.push(todo)">
...
<div v-if="hiddenTodos.includes(todo)"

Ng-hide and show in ng-repeat

I am trying to get the button to toggle only on the one clicked, but as I am using ng-repeat, it all changes together. How do i fix it so that it would only change on the one clicked?
HTML:
<ul>
<li class="displaySubCategory" ng-repeat="communityTheme in community | startFrom:currentPage*pageSize | limitTo:pageSize">
<div class="categoryImg">
<img src="img/csvIcon.png" />
<img src="img/shpIcon.png" />
</div>
<div class="categoryDesc">
<p>{{communityTheme.THEMENAME}}</p>
<a ng-href="https://assets.onemap.sg/shp/{{SHPFile}}" ng-click="getSHP(communityTheme.QUERYNAME)" target="_blank" download>SHP</a> |
<a ng-href="https://assets.onemap.sg/kml/{{KMLFile}}" ng-click="getKML(communityTheme.QUERYNAME)" target="_blank" download>KML</a> |
View on Map
Remove Marker
<!-- <a href="" ng-click="getData(communityTheme.QUERYNAME)" download>View Data</a> -->
</div>
</li>
</ul>
JS:
$scope.viewMarker = true;
$scope.getMapData = function (msg) {
$scope.viewMarker = !$scope.viewMarker;
}
Before:
After:
Modified code:
$scope.viewMarker = true;
$scope.getMapData = function (msg, passedIndex) {
if($scope.community[passedIndex].visibility)
{
$scope.community[passedIndex].visibility =false;
} else {
$scope.community[passedIndex].visibility = true;
}
$scope.viewMarker = !$scope.viewMarker;
<ul>
<li class="displaySubCategory" ng-repeat="communityTheme in community | startFrom:currentPage*pageSize | limitTo:pageSize">
<div class="categoryImg">
<img src="img/csvIcon.png" />
<img src="img/shpIcon.png" />
</div>
<div class="categoryDesc">
<p>{{communityTheme.THEMENAME}}</p>
<a ng-href="https://assets.onemap.sg/shp/{{SHPFile}}" ng-click="getSHP(communityTheme.QUERYNAME)" target="_blank" download>SHP</a> |
<a ng-href="https://assets.onemap.sg/kml/{{KMLFile}}" ng-click="getKML(communityTheme.QUERYNAME)" target="_blank" download>KML</a> |
View on Map
Remove Marker
<!-- <a href="" ng-click="getData(communityTheme.QUERYNAME)" download>View Data</a> -->
</div>
</li>
</ul>
this should help clarify...
var app = angular.module("test", []);
app.controller("myCtrl", function($scope) {
$scope.community = [
{ THEMENAME:"Milk", QUERYNAME:"Milk", visibility:true}
, { THEMENAME:"Bread", QUERYNAME:"Milk", visibility:true}
, { THEMENAME:"Cheese", QUERYNAME:"Milk", visibility:true}
];
$scope.getMapData = function(passedQueryName, passedIndex){
/*do what you were doing, just add this one more point*/
if($scope.community[passedIndex].visibility) {$scope.community[passedIndex].visibility =false;}
else {$scope.community[passedIndex].visibility = true;}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<div ng-app="test">
<div ng-app="myShoppingList" ng-controller="myCtrl">
<div ng-repeat="communityTheme in community ">
{{x}}
<div class="categoryDesc">
<p>{{communityTheme.THEMENAME}} # {{$index}}</p>
<a ng-href="https://assets.onemap.sg/shp/{{SHPFile}}" ng-click="getSHP(communityTheme.QUERYNAME)" target="_blank" download>SHP</a> |
<a ng-href="https://assets.onemap.sg/kml/{{KMLFile}}" ng-click="getKML(communityTheme.QUERYNAME)" target="_blank" download>KML</a> |
View on Map
Remove Marker
<!-- <a href="" ng-click="getData(communityTheme.QUERYNAME)" download>View Data</a> -->
</div>
</div>
</div>
<p>So far we have made an HTML list based on the items of an array.</p>
</div>
You can try using it like the below code where we'll be creating dynamic variable 'viewMarker' in the same object and to consider it's default value as 'false' and to toggle it in the getMapData function by inverting its value.
Template:
<ul>
<li class="displaySubCategory" ng-repeat="communityTheme in community | startFrom:currentPage*pageSize | limitTo:pageSize">
<div class="categoryImg">
<img src="img/csvIcon.png" />
<img src="img/shpIcon.png" />
</div>
<div class="categoryDesc">
<p>{{communityTheme.THEMENAME}}</p>
<a ng-href="https://assets.onemap.sg/shp/{{SHPFile}}" ng-click="getSHP(communityTheme.QUERYNAME)" target="_blank" download>SHP</a> |
<a ng-href="https://assets.onemap.sg/kml/{{KMLFile}}" ng-click="getKML(communityTheme.QUERYNAME)" target="_blank" download>KML</a> |
View on Map
Remove Marker
<!-- <a href="" ng-click="getData(communityTheme.QUERYNAME)" download>View Data</a> -->
</div>
</li>
</ul>
Controller:
$scope.getMapData = function (obj) {
obj.viewMarker = !obj.viewMarker;
}
As i see now you are using the same variable to handle the toggling part. you should have an individual variable with a boolean value to handle the toggling so that you can handle each element individually.
DEMO

Is it possible to remove size from the end a responsive image path?

I want to remove the -500x500 part from the image so that I can show the actual image.
Here's the complete HTML if anybody wants to take a look:
<div id="speakers_list1" class="wpb_row vc_row mk-fullwidth-false attched-false vc_row-fluid js-master-row mk-in-viewport">
<div style="" class="vc_col-sm-12 wpb_column column_container _ height-full">
<div id="box-14" class="mk-employees a_margin-bottom-10 a_margin-top-10 four-column u6col u5col o0col o1col o2col o3col mk-employees-grayscale classic c_cs ">
<ul>
<li class="mk-employee-item a_colitem a_align-center a_display-inline-block a_float-left m_7">
<div class="item-holder">
<div class="team-thumbnail a_position-relative a_width-100-per a_height-100-per a_overflow-hidden rounded-true">
<a href="http://developer.designprowebsolutions.com/sufi-intensive/team/imam-abdoulaye-ndaw/">
<img alt="Imam Abdoulaye Ndaw" title="Imam Abdoulaye Ndaw" src="http://developer.designprowebsolutions.com/sufi-intensive/wp-content/uploads/2017/02/imam-abdoulahy-ndaw-500x500.jpg">
</a>
<div class="employee-hover-overlay a_m_fly-top-left a_opacity-100 "></div>
</div>
<div class="team-info-wrapper m_7" itemscope="itemscope" itemtype="https://schema.org/Person">
<a class="team-member-name" href="http://developer.designprowebsolutions.com/sufi-intensive/team/imam-abdoulaye-ndaw/">
<span class="team-member-name a_font-16 a_display-block a_font-weight-bold a_text-transform-up a_color-333">Imam Abdoulaye Ndaw</span>
</a>
<span class="team-member-position a_font-12 a_text-transform-up a_display-block a_color-777 a_letter-spacing-1">Imam & Ustadz</span>
<div class="team-member-desc a_margin-top-20 a_margin-bottom-10 a_display-block"></div>
</div>
</div>
A quick way(not beautiful) is to replace the src of the element
src is a attribute on the element, so you can get the value with $(obj).attr("src") or set the value with $(obj).attr("src","newValue")
Edit I created a function so you can do this multiple times with multiple objects
Either add a class to the img, you want to change or call it by an attribute.
Class: fixImage($('.removeRatio'), "-500x500") or
Attribute: fixImage($('[title="Imam Abdoulaye Ndaw"]'), "-500x500")
console.log("This was my SRC: " + $('.removeRatio').attr("src"))
function fixImage(obj, removestring)
{
obj.attr("src", obj.attr("src").replace(removestring, ""))
}
fixImage($('.removeRatio'), "-500x500")
console.log("This now IS my SRC: " + $('.removeRatio').attr("src"))
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="speakers_list1" class="wpb_row vc_row mk-fullwidth-false attched-false vc_row-fluid js-master-row mk-in-viewport">
<div style="" class="vc_col-sm-12 wpb_column column_container _ height-full">
<div id="box-14" class="mk-employees a_margin-bottom-10 a_margin-top-10 four-column u6col u5col o0col o1col o2col o3col mk-employees-grayscale classic c_cs ">
<ul>
<li class="mk-employee-item a_colitem a_align-center a_display-inline-block a_float-left m_7">
<div class="item-holder">
<div class="team-thumbnail a_position-relative a_width-100-per a_height-100-per a_overflow-hidden rounded-true">
<a href="http://developer.designprowebsolutions.com/sufi-intensive/team/imam-abdoulaye-ndaw/">
<img class="removeRatio" alt="Imam Abdoulaye Ndaw" title="Imam Abdoulaye Ndaw" src="http://developer.designprowebsolutions.com/sufi-intensive/wp-content/uploads/2017/02/imam-abdoulahy-ndaw-500x500.jpg">
</a>
<div class="employee-hover-overlay a_m_fly-top-left a_opacity-100 "></div>
</div>
<div class="team-info-wrapper m_7" itemscope="itemscope" itemtype="https://schema.org/Person">
<a class="team-member-name" href="http://developer.designprowebsolutions.com/sufi-intensive/team/imam-abdoulaye-ndaw/">
<span class="team-member-name a_font-16 a_display-block a_font-weight-bold a_text-transform-up a_color-333">Imam Abdoulaye Ndaw</span>
</a>
<span class="team-member-position a_font-12 a_text-transform-up a_display-block a_color-777 a_letter-spacing-1">Imam & Ustadz</span>
<div class="team-member-desc a_margin-top-20 a_margin-bottom-10 a_display-block"></div>
</div>
</div>

JavaScript array skipping values

I have this function that loops through all of the <img> tags and adds their sourcesrc into an array. When the user clicks on the main parent div, Bootstrap's modal fades in showing the rest of the gallery.
My problem is, whenever I press the right chevron on a specific div it shows the gallery and slides them perfectly but when I click on another div, the array skips two values and displays the third one instead.
To explain my problem more briefly, lets say I have this array:
arr = [1,2,3,4,5]
When I click the next button the first time it works perfectly
1 => 2 => 3 => 4 => 5
But when I click on another div and press next:
1 => 2 => 5
Here's a working demo of what I have done till now.
HTML:
<div class="col-md-4 col-sm-4 col-lg-4 padBtm10">
<a data-toggle="modal" data-target="#exampleModal" href="#" class="modal-trigger deco-none" onclick="return false;">
<div class="card that_img radius10">
<img data-caption-title="First caption" class="card-img-top img-responsive caption" src="http://dummyimage.com/500x300/000/fff" alt="Card image cap" />
<span class="fa fa-search search fa-3x blue"></span>
<div class="redbg radiusBtm10 white card-block">
<h4 class="card-title">Lorem Ipsum</h4>
</div>
<div class="imgs-album">
<img src="http://dummyimage.com/500x300/000/fff" class="img-responsive full" data-caption-title="First caption for slider 1" />
<img src="http://dummyimage.com/500x300/ddd/fff" class="img-responsive full" data-caption-title="First caption for slider 2" />
<img src="http://dummyimage.com/500x300/aaa/fff" class="img-responsive full" data-caption-title="First caption for slider 3" />
<img src="http://dummyimage.com/500x300/ccc/000" class="img-responsive full" data-caption-title="First caption for slider 4" />
</div>
</div>
</a>
</div>
update (HTML structure for the modal)
<div class="modal breaker fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body noPad">
<button type="button" class="close-pop close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<div class="">
<a href="#" onclick="return false;">
<span class="fa fa-chevron-right fa-2x right white"></span>
</a>
<a href="#" onclick="return false;">
<span class="fa fa-chevron-left fa-2x left white"></span>
</a>
</div>
<div class="pop-image">
<img src="" class="img-responsive full">
</div>
<h4 class="modal_caption"></h4>
</div>
</div>
</div>
</div>
JavaScript:
(function() {
var ready = function() {
$(".that_img").hover(function() {
$(this).find("span.search").css("display", "block");
}, function() {
$(this).find("span.search").css("display", "none");
});
$(".that_img").on({
click: function() {
var img_src_arr = $(this).find(".imgs-album")
.children("img").map(function() {
return $(this).attr("src");
}).get();
var img_data_cap = $(this).find(".imgs-album")
.children("img").map(function() {
return $(this).data("caption-title");
}).get();
$(".pop-image").find("img").attr("src", img_src_arr[0]);
$(".modal_caption").html(img_data_cap[0]);
var counter = 0;
counter >= 0 ? $(".left").hide() : $(".left").show();
$(".right").on({
click: function() {
counter += 1;
if (counter == 1) {
$(".left").show()
}
var next = $(".pop-image").find("img")
.attr("src", img_src_arr[counter]);
var next_cap = $(".modal_caption")
.html(img_data_cap[counter]);
if (counter > (img_src_arr.length - 2)) {
$(".right").hide();
$(".left").show();
}
}
});
$(".left").on({
click: function() {
counter -= 1;
$(".right").show();
if (counter === 0) {
$(".right").show();
$(".left").hide();
}
$(".pop-image").find("img")
.attr("src", img_src_arr[counter]);
var prev = $(".modal_caption").html(img_data_cap[counter]);
}
});
}
});
}
$(document).ready(ready);
}).call(this);
The problem occurs because every time an image is clicked, click-handlers are added. With the first image everything seems fine because .left and .right have, at that point, a single click handler. Upon clicking another image, new click-handlers are added and now when you click a chevron, the 2 handlers are being executed resulting in your counter going up, or down, by 2 instead of 1. To prevent this from happening you will have to unbind the handlers from the object.
Change these lines, (explanation here)
$(".right").on({
$(".left").on({
to,
$(".right").off().on({
$(".left").off().on({
And change this line,
counter >= 0 ? $(".left").hide() : $(".left").show();
to,
$(".right").show()
$(".left").hide()
Edit : as mentioned by juhana unbind() is deprecated, so use off() instead.

Changing multiple images with JQuery

So here is the JQuery I am using
jQuery(document).ready(function($) {
$('.ltwitch').each(function () {
var tnick = $(this).data('tnick');
var span = $(this).next();
$.getJSON("https://api.twitch.tv/kraken/streams/"+tnick+".json?callback=?", function(c) {
if (c.stream == null) {
span.html("Offline");
} else {
span.html("Online");
}
});
});
});
And the HTML that was with it when I found it
<a class="ltwitch" href="http://www.twitch.tv/ifstudios" data-tnick="IFStudios">IFStudios</a> (<span>...</span>)
RoosterTeeth (...)
Now what I want to do, I have HTML that looks like this
<a href="#portfolioModal3" class="portfolio-link" data-toggle="modal">
<div class="portfolio-hover">
<div class="portfolio-hover-content">
<i class="fa fa-plus fa-3x"></i>
</div>
</div>
<img src="img/portfolio/sweet.png" class="img-responsive" alt="">
</a>
Basically when a channel becomes live I want to switch the img src from the image I have it set to, to the same image with -online on the end. So I can have multiple pictures on the website, but I can have the images change dependent on who is live and who isn't.
So if I have
<a href="#portfolioModal3" class="portfolio-link" data-toggle="modal">
<div class="portfolio-hover">
<div class="portfolio-hover-content">
<i class="fa fa-plus fa-3x"></i>
</div>
</div>
<img src="img/portfolio/sweet.png" class="img-responsive" alt="">
</a>
When her channel goes live, it will turn to
<a href="#portfolioModal3" class="portfolio-link" data-toggle="modal">
<div class="portfolio-hover">
<div class="portfolio-hover-content">
<i class="fa fa-plus fa-3x"></i>
</div>
</div>
<img src="img/portfolio/sweet-online.png" class="img-responsive" alt="">
Or if it was
<img src="img/portfolio/carrot.png"
it would turn to
<img src="img/portfolio/carrot-online.png"
Any ideas?
Try the below code
jQuery(document).ready(function($) {
$('.ltwitch').each(function () {
var tnick = $(this).data('tnick');
var span = $(this).next();
$.getJSON("https://api.twitch.tv/kraken/streams/"+tnick+".json?callback=?", function(c) {
var img = $(img-selector);
var source = img.attr('src');
if (c.stream != null) {
// Online
if(source.indexOf('.png') != -1){
source = source.replace(".png", "-online.png");
img.attr('src',source);
}
}
else{
// Offline
source.replace("-online", "");
img.attr('src',source);
}
});
});
});
Note: You have to pass the correct image selector to $(img-selector). Also call the same function again for refreshing

Categories