Owl Carousel not updating when image urls are changed on click - javascript

I have a product page with images and product description that all loads dynamically from a json file. Everything works perfectly except for the owl carousel when I click on either the prev/next arrows. The main image and the data updates as it should, but the carousel does not.
I logged the new image urls and they are being updated properly.
I tried using this everywhere in the code
$("#owl-focus").trigger('refresh.owl.carousel');
This is the javascript for the page
// ========== Compile Product Data =======================================
$.getJSON("../../json/guitars.json", function(data) {
var jsonLength = data.length
// ------- Parse & Returns URL Parameters -----------------------------
function getUrlVars(guitar) {
var vars = {}
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
})
return vars
}
// ------------ Append Clicked Image -------------------------------------
var guitar = parseInt(getUrlVars()["product"], 10)
loadGuitar(guitar)
function loadGuitar(guitar) {
// Images
var image1 = data[guitar].img1
var image2 = data[guitar].img2
var image3 = data[guitar].img3
var image4 = data[guitar].img4
var alt = data[guitar].alt
// description
var title = data[guitar].title
var brand = data[guitar].brand
var code = data[guitar].code
var price = data[guitar].price
var description = data[guitar].description
var specs = data[guitar].specs
$('#clickImg').attr({src: `../${image1}`, alt: `${alt}`})
$('#img1').attr({src: `../${image1}`, alt: `${alt}`})
$('#img2').attr({src: `../${image2}`, alt: `${alt}`})
$('#img3').attr({src: `../${image3}`, alt: `${alt}`})
$('#img4').attr({src: `../${image4}`, alt: `${alt}`})
$('#title').html(title)
$('#brand').html(brand)
$('#variant-sku').html(code)
$('#price').html(price)
$('#description').html(description)
$('#specs').empty();
specs.forEach(spec => {
$("#specs"). append(`<li>${spec}</li>`)
})
}
// -------------- Owl Carousel -------------------------------------------
$(document).ready(function () {
$('#owl-focus').owlCarousel({
loop: true,
margin: 10,
nav: true,
navText: [$('.owl-navigation .owl-nav-prev'), $('.owl-navigation .owl-nav-next')],
responsiveClass: true,
responsive: {
0: {
items: 3,
},
1050: {
items: 4,
}
}
})
})
// -------- Next / Previous Arrows -------------------------------------
$("#prev-btn").click(function() {
if (guitar === 0) {
guitar = jsonLength - 1
} else {
guitar = guitar - 1
}
loadGuitar(guitar)
onPageChg()
})
$("#next-btn").click(function() {
if (guitar === jsonLength - 1) {
guitar = 0
} else {
guitar = guitar + 1
}
loadGuitar(guitar)
onPageChg()
})
})
// ========== Compile Product Data End ===================================

Figured it out. Instead of trying to reload owl I reloaded the page as I should have with new data. Similar functions that take me to that product page in the first place with a few adjustments.
$("#prev-btn").on("click", function(e) {
$.getJSON("../../json/guitars.json", function(json) {
if (guitar === 0) {
new_id = jsonLength - 1
} else {
new_id = guitar - 1
}
window.location.href = "product.html?product=" + new_id
})
})
$("#next-btn").on("click", function(e) {
$.getJSON("../../json/guitars.json", function(json) {
if (guitar === jsonLength - 1) {
new_id = 0
} else {
new_id = guitar + 1
}
window.location.href = "product.html?product=" + new_id
})
})
Before I was just changing the attributes on the photos, description, etc

Related

how to append a div content to a class only once?

I have several images as slide. On clicking next button, images are being slide shown but i want to add a text for each image over the image.
javacsript code:
afterShow: function( instance, current ) {
//alert($(this).find('img').attr('alt'));
var url = window.location.href;
var cat = url.substring(url.lastIndexOf('#') + 1);
var cats = cat.split('-');
catId= cats[0];
var index=catId+$("[data-fancybox-index]").html();
//alert($("[data-fancybox-index]").html());
//$('.fancybox-slide').children(".imagecontainer").remove();
//alert($("#d_" + index).length);
if($("#d_" + index).length == 0) {
var strDiv='<div id="d_'+index+'" class="centerdivCont"></div>';
$(".fancybox-content").append(strDiv);
return false;
}
/*if($("#d_" + index).length> 0) {
var strDiv='<div id="d_'+index+'" class="centerdivCont"></div>';
$(".fancybox-content").remove(strDiv);
}else{
var strDiv='<div id="d_'+index+'" class="centerdivCont"></div>';
$(".fancybox-content").append(strDiv);
}*/
//alert($("#d_" + index).length);
//$(".fancybox-slide").append($('#'+index).html());
},

Update live JavaScript Array while pushing elements to HTML ID

I am facing a slight dilemma as a JavaScript newbie. Let me explain the script:
I have implemented a JavaScript function rss() which pulls from an internet RSS news feed and saves the news headlines into an array newsArray[].
The function headlinesInsert() should push every item in the array to the HTML ID #headlineInsert, similarly to how it is shown here.
However, the linked example's textlist variable (which should be replaced with my local newsArray[]) does not seem to be 'compatible' for some reason as when replacing nothing shows on the HTML side.
The idea is that the rss() function updates the global newsArray[] with new headlines every 10 minutes while the headlinesInsert() pushes this data to the HTML ID constantly (as per the linked example).
With my limited knowledge of JavaScript, I am hoping someone could help me set the following code right and put the idea into action.
// Push RSS Headlines into HTML ID
var newsArray = [];
var listTicker = function headlinesInsert(options) {
var defaults = {
list: [],
startIndex:0,
interval: 8 * 1000,
}
var options = $.extend(defaults, options);
var listTickerInner = function headlinesInsert(index) {
if (options.list.length == 0) return;
if (!index || index < 0 || index > options.list.length) index = 0;
var value = options.list[index];
options.trickerPanel.fadeOut(function headlinesInsert() {
$(this).html(value).fadeIn();
});
var nextIndex = (index + 1) % options.list.length;
setTimeout(function headlinesInsert() {
listTickerInner(nextIndex);
}, options.interval);
};
listTickerInner(options.startIndex);
}
// The following line should hold the values of newsArray[]
var textlist = new Array("News Headline 1", "News Headline 2", "News Headline 3", "News Headline 4");
$(function headlinesInsert() {
listTicker({
list: textlist ,
startIndex:0,
trickerPanel: $('#headlineInsert'),
interval: 8 * 1000,
});
});
$(function slow(){
// Parse News Headlines into array
function rss() {
$.getJSON("https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fwww.stuff.co.nz%2Frss", function(data) {
newsArray = [];
for (var i = 0; i < data.items.length; i++){
newsArray[i] = (data.items[i].title);
}
console.log(newsArray);
})}
// Refresh functions ever 10 minutes
rss()
setInterval(function slow() {
rss();
}, 600000); // 10 Minute refresh time
});
Check following code. You need to initialise listTicker once rss feed is loaded.
<script src='https://code.jquery.com/jquery-3.2.1.min.js'></script>
<script>
var listTicker = function(options) {
var defaults = {
list: [],
startIndex: 0,
interval: 3 * 1000,
}
var options = $.extend(defaults, options);
var listTickerInner = function(index) {
if (options.list.length == 0) return;
if (!index || index < 0 || index > options.list.length) index = 0;
var value = options.list[index];
options.trickerPanel.fadeOut(function() {
$(this).html(value).fadeIn();
});
var nextIndex = (index + 1) % options.list.length;
setTimeout(function() {
listTickerInner(nextIndex);
}, options.interval);
};
listTickerInner(options.startIndex);
}
var textlist = new Array("news1", "news2", "news3");
$(function() {
function rss() {
$.getJSON("https://api.rss2json.com/v1/api.json?rss_url=https%3A%2F%2Fwww.stuff.co.nz%2Frss", function(data) {
newsArray = [];
for (var i = 0; i < data.items.length; i++) {
newsArray[i] = (data.items[i].title);
}
console.log(newsArray);
listTicker({
list: newsArray,
startIndex: 0,
trickerPanel: $('#newsPanel'),
interval: 3 * 1000,
});
})
}
rss();
});
</script>
<div id='newsPanel' />

trying to show chessboard js in odoo form widget, no error no pieces

Hi i´m trying to show chessboardjs on a form view in odoo backend, I finally make the widget to show the board, but the pieces are hidden, I don´t know why because seems to work fine, except for the pieces. If I use dragable : true in the options and move a hidden piece then the board is rendered with all the pieces. do I´m missing something, on my code that the chessboard its not rendered well??
here is mi widget code:
(function (instance) {
var _t = instance.web._t,
_lt = instance.web._lt;
var QWeb = instance.web.qweb;
openerp.chess_base = function (instance, local) {
local.YourWidgetClassName = instance.web.form.FormWidget.extend({
start: function () {
this.$el.append('<div id="board" style="width: 300px">BOARD GOES HERE</div>'); // creating the board in the DOM
this.onBoard();
},
onBoard: function (position, orientation) {
if (!position) {
this.position = 'start'
} else {
this.position = position
}
if (!orientation) {
this.orientation = 'white'
} else {
this.orientation = orientation
}
this.el_board = this.$('#board');
this.cfg = {
position: this.position,
orientation: this.orientation,
draggable: false,
pieceTheme: '/chess_base/static/img/chesspieces/wikipedia/{piece}.png'
};
this.board = ChessBoard(this.el_board, this.cfg);
}
});
instance.web.form.custom_widgets.add('widget_tag_name', 'instance.chess_base.YourWidgetClassName');
}
})(openerp);
I don't know why but this solve the issue, if someone have an explanation to me please ...
(function (instance) {
var _t = instance.web._t,
_lt = instance.web._lt;
var QWeb = instance.web.qweb;
openerp.chess_base = function (instance, local) {
local.ShowBoard = instance.web.form.FormWidget.extend({
start: function () {
this.$el.append('<div id="board" style="width: 300px">BOARD GOES HERE</div>');
this.show_board();
},
show_board: function () {
var Game = new instance.web.Model("chess.game"),
record_id = this.field_manager.datarecord.id,
record_name = this.field_manager.datarecord.name,
self = this;
self.el_board = self.$('#board');
Game.query(['pgn']).filter([['id', '=', record_id], ['name', '=', record_name]]).all().then(function (data) {
console.log(data);
self.cfg = {
position: data[0].pgn,
orientation: 'white',
pieceTheme: '/chess_base/static/img/chesspieces/wikipedia/{piece}.png'
};
ChessBoard(self.el_board, self.cfg);
});
}
});
instance.web.form.custom_widgets.add('board', 'instance.chess_base.ShowBoard');
}
})(openerp);

Multi-item responsive carousel

I'm building a website that requires a carousel to be implemented. Because this website is built on AngularJS I wanted to go with Angulars Boostrap Carousel, however, this carousel appears to only allow one image at a time.
What I will need will be 3 images at a time on desktop, on a tablet 2 images and on mobile 1. So there's a significant element of responsive design involved here too.
Does anyone have any experince with this that doesn't involve JQuery? I'm not opposed to it but have been told by a senior member of the team to try to source an alternative, if any.
What I tried from Angulars bootstrap:
$scope.getPromoURLs = function() {
var subObj = myJSON.response.details.promotionalSpots;
for( var keys in subObj ) {
var value = subObj[keys].promotionUrl;
$scope.slides.push( value );
}
};
// Builts an array of promotional URLS to from a JSON object to source the images
$scope.getPromoURLs();
$scope.addSlide = function () {
// Test to determine if 3 images can be pulled together - FAILS
var newWidth = 600 + slides.length;
slides.push({
image: ''+slides[0]+''+slides[1] // etc
// Tried to stitch images together here
});
};
// TODO Should examine array length not hardcoded 4
for (var i = 0; i < 4; i++) {
$scope.addSlide();
}
ui-bootstrap's carousel is not a good choice, it has other drawback like isolated scope on each slide.
I'm using https://github.com/revolunet/angular-carousel which support multi item on each slide.
Because this directive support ng-repeat. You easy change you collection and using nested ng-repeat to set different number of items in each slide.
<ul rn-carousel class="image">
<li ng-repeat="images in imageCollection">
<div ng-repeat="image in images" class="layer">{{ image }}</div>
</li>
</ul>
As you have already defined 3 break points. We just need to reconstruct the imageCollection array when viewport size changed.
$window.on('resize', function() {
var width = $window.width();
if(width > 900) {
// desktop
rebuildSlide(3);
} else if(width <= 900 && width > 480) {
// tablet
rebuildSlide(2);
} else {
// phone
rebuildSlide(1);
}
// don't forget manually trigger $digest()
$scope.$digest();
});
function rebuildSlide(n) {
var imageCollection = [],
slide = [],
index;
// values is your actual data collection.
for(index = 0; index < values.length; index++) {
if(slide.length === n) {
imageCollection.push(slide);
slide = [];
}
slide.push(values[index]);
}
imageCollection.push(slide);
$scope.imageCollection = imageCollection;
}
So, I tried this one so as to make angularjs Carousel (ui.bootstrap.carousel) to work with multi items per animation. I have also tried to apply [Detection for Responsive Websites using AngularJS].2
Take a look here: http://plnkr.co/edit/QhBQpG2nCAnfsb9mpTvj?p=preview
Results:
1 ) One Item (Mobile Version) :
2 ) Two Items (Tablet Version) :
3 ) Three Items (Desktop Version) :
PART 2:
It can also detect the resolution of the window so as to determine if it is tablet,mobile or desktop following this tutorial...
Try to use this values: "mobile, tablet, desktop" to see the three different view versions.
Demonstration of the tablet version:
var app = angular.module('myApp', ['ui.bootstrap', 'angular-responsive']);
app.controller('MainCtrl', function($scope) {
$scope.displayMode = 'mobile'; // default value
$scope.$watch('displayMode', function(value) {
switch (value) {
case 'mobile':
// do stuff for mobile mode
console.log(value);
break;
case 'tablet':
// do stuff for tablet mode
console.log(value);
break;
}
});
});
function CarouselDemoCtrl($scope) {
var whatDevice = $scope.nowDevice;
$scope.myInterval = 7000;
$scope.slides = [{
image: 'http://placekitten.com/221/200',
text: 'Kitten.'
}, {
image: 'http://placekitten.com/241/200',
text: 'Kitty!'
}, {
image: 'http://placekitten.com/223/200',
text: 'Cat.'
}, {
image: 'http://placekitten.com/224/200',
text: 'Feline!'
}, {
image: 'http://placekitten.com/225/200',
text: 'Cat.'
}, {
image: 'http://placekitten.com/226/200',
text: 'Feline!'
}, {
image: 'http://placekitten.com/227/200',
text: 'Cat.'
}, {
image: 'http://placekitten.com/228/200',
text: 'Feline!'
}, {
image: 'http://placekitten.com/229/200',
text: 'Cat.'
}, {
image: 'http://placekitten.com/230/200',
text: 'Feline!'
}];
var i, first = [],
second, third;
var many = 1;
//##################################################
//Need to be changed to update the carousel since the resolution changed
$scope.displayMode = "tablet";
//##################################################
if ($scope.displayMode == "mobile") {many = 1;}
else if ($scope.displayMode == "tablet") {many = 2;}
else {many = 3;}
for (i = 0; i < $scope.slides.length; i += many) {
second = {
image1: $scope.slides[i]
};
if (many == 1) {}
if ($scope.slides[i + 1] && (many == 2 || many == 3)) {
second.image2 = $scope.slides[i + 1];
}
if ($scope.slides[i + (many - 1)] && many == 3) {
second.image3 = $scope.slides[i + 2];
}
first.push(second);
}
$scope.groupedSlides = first;
}
app.directive('dnDisplayMode', function($window) {
return {
restrict: 'A',
scope: {
dnDisplayMode: '='
},
template: '<span class="mobile"></span><span class="tablet"></span><span class="tablet-landscape"></span><span class="desktop"></span>',
link: function(scope, elem, attrs) {
var markers = elem.find('span');
function isVisible(element) {
return element && element.style.display != 'none' && element.offsetWidth && element.offsetHeight;
}
function update() {
angular.forEach(markers, function(element) {
if (isVisible(element)) {
scope.dnDisplayMode = element.className;
return false;
}
});
}
var t;
angular.element($window).bind('resize', function() {
clearTimeout(t);
t = setTimeout(function() {
update();
scope.$apply();
}, 300);
});
update();
}
};
});
Hope it helps!

Pulling YouTube title's from custom player

I'm working on building a custom YouTube player to embed a video feed on a website. I'm new to this, and I haven't had much luck searching around the Web.
Using snippets of useful code from tutorials, I've created a main video player and a carousel of thumbnails for users to click on to load that video into the player. The only thing missing, however, is I want the currently selected video's title to appear below the iframe tag. Any help on this? Or can anybody point me in the right direction?
Here's my script:
<script>
(function() {
function createPlayer(jqe, video, options) {
var ifr = $('iframe', jqe);
if (ifr.length === 0) {
ifr = $('<iframe scrolling="no">');
ifr.addClass('player');
}
var src = 'http://www.youtube.com/embed/' + video.id;
if (options.playopts) {
src += '?';
for (var k in options.playopts) {
src+= k + '=' + options.playopts[k] + '&';
}
src += '_a=b';
}
ifr.attr('src', src);
jqe.append(ifr);
}
function createCarousel(jqe, videos, options) {
var car = $('div.carousel', jqe);
if (car.length === 0) {
car = $('<div>');
car.addClass('carousel');
jqe.append(car);
}
$.each(videos, function(i,video) {
options.thumbnail(car, video, options);
});
}
function createThumbnail(jqe, video, options) {
var imgurl = video.thumbnails[0].url;
var img = $('img[src="' + imgurl + '"]');
if (img.length !== 0) return;
img = $('<img>');
img.addClass('thumbnail');
jqe.append(img);
img.attr('src', imgurl);
img.attr('title', video.title);
img.click(function() {
options.player(options.maindiv, video, $.extend(true,{},options,{playopts:{autoplay:1}}));
});
}
var defoptions = {
autoplay: false,
user: null,
player: createPlayer,
carousel: createCarousel,
thumbnail: createThumbnail,
loaded: function() {},
playopts: {
autoplay: 0,
egm: 1,
autohide: 1,
fs: 1,
showinfo: 0
}
};
$.fn.extend({
youTubeChannel: function(options) {
var md = $(this);
md.addClass('youtube');
var allopts = $.extend(true, {}, defoptions, options);
allopts.maindiv = md;
$.getJSON('http://gdata.youtube.com/feeds/users/' + allopts.user + '/uploads?alt=json-in-script&format=5&callback=?', null, function(data) {
var feed = data.feed;
var videos = [];
$.each(feed.entry, function(i, entry) {
var video = {
title: entry.title.$t,
id: entry.id.$t.match('[^/]*$'),
thumbnails: entry.media$group.media$thumbnail
};
videos.push(video);
});
allopts.allvideos = videos;
allopts.carousel(md, videos, allopts);
allopts.player(md, videos[0], allopts);
allopts.loaded(videos, allopts);
});
}
});
})();
$(function() {
$('#player').youTubeChannel({user:'oklahomadaily'});
});
</script>
And here's my HTML:
<div class="video">
<div class="boxTitle">Featured videos</div>
<div id="player"></div>
<div id="title"><p class="multimedia">Could not find a description...</p></div>
</div>
Thanks for your patience and assistance.

Categories

Resources