I'm moving some of my html/javascript pages over to AngularJS. Previously, my script (an HTML5 audio player) rendered some HTML elements on the page and then ran some script to use those elements, thusly:
audioplayer.html:
...
<div id="timeline">
<div id="showElapsed">
<div class="bg">
</div>
</div>
<div id="playhead"></div>
</div>
...
<script>
var playhead = document.getElementById('playhead'); // playhead
var timeline = document.getElementById('timeline'); // timeline
// timeline width adjusted for playhead
var timelineWidth = timeline.offsetWidth - playhead.offsetWidth;
...
Now i'd like to move this into a controller / view layout in angular, so;
index.html
...
<div ng-controller="AudioPlayerController">
<div ng-include="'views/audioPlayerView.html'"></div>
</div>
...
main.js
...
function AudioPlayerController($scope) {
var playhead = document.getElementById('playhead'); // playhead
var timeline = document.getElementById('timeline'); // timeline
// timeline width adjusted for playhead
var timelineWidth = timeline.offsetWidth - playhead.offsetWidth;
...
audioPlayerView.html:
...
<div id="timeline">
<div id="showElapsed">
<div class="bg">
</div>
</div>
<div id="playhead"></div>
</div>
...
Now I have a problem - document.getElementById('timeline'); doesn't return anything because its moved to a controller. Furthermore, the controller is called BEFORE the view, so how can the controller reference an element FROM the view?
I realize this is basic Angular layout stuff, but I can't figure it out. Could someone help me think in a more angular way please!? Thanks.
For dom interaction in angular you have directives elements
that implemented in the view.
directive link also complie after view is loaded, so no problem here.
note their declarations are written in camel case on the view, so:
javascript:
angular.module('myApp')
.directive('audioPlayer', function() {
return {
restrict: 'A',
template: 'path-to-your-page/audioPlayerView.html',
link: function(element) {
var playhead = element.find('playhead');
// timeline width adjusted for playhead
var timelineWidth = element.offsetWidth - playhead.offsetWidth;
}
};
});
html:
<div audio-player>
<div id="showElapsed">
<div class="bg">
</div>
</div>
<div id="playhead"></div>
</div>
note that,
in "angular way" you shouldn't make
document.getElementById(), just ==> angular.element()
Related
I'm trying to change the background of the body on my HTML doc using some basic JS functions. I have set the function to target a specific ID, and then the style.background tag, if it is the current background image, then set it to another one I specified, else keep the same image. I have tried changing the code countless times now, but still can't seem to get it to change the background. Any help with this would be appreciated.
HTML:
<div class="bg-image"
style="background-image: url('./img/frankie.jpg');
height: 100vh" id="bacgr"> <!--SETS BACKGROUND using id tag to change w/ JS-->
<main role="main" class="container d-flex justify-content-center">
<div class="starter-template">
<h1>Bootstrap starter template</h1>
<p class="lead">Use this document as a way to quickly start any new project.<br> All you get is this text and a mostly barebones HTML document.</p>
</div>
</main>
</div>
JS:
let myImage = document.getElementById('bacgr').style.backgroundImage; //have to target specific image(like an array ([0])), put inside div w/ id.
myImage.onclick = function() {
if(myImage === "url('./img/frankie.jpg')") {
myImage == "url('./img/jesus_mobile.jpg')";
} else {
myImage == "url('./img/frankie.jpg')";
}
}
Try this:
const el = document.getElementById('bacgr');
el.onclick = function() {
if(this.style.backgroundImage === "url('./img/frankie.jpg')") {
this.style.backgroundImage = "url('./img/jesus_mobile.jpg')";
} else {
this.style.backgroundImage = "url('./img/frankie.jpg')";
}
}
Here is the example
You are changing only the URL, but that will not be assigned back to the dom element.
const el = document.getElementById('bacgr');
let prev = 'url("https://images.unsplash.com/photo-1570215171323-4ec328f3f5fa")';
el.onclick = function() {
el.style.backgroundImage = prev === el.style.backgroundImage ? 'url("https://images.unsplash.com/photo-1583508915901-b5f84c1dcde1")' : prev;
}
<div class="bg-image" style="background-image: url('https://images.unsplash.com/photo-1570215171323-4ec328f3f5fa');
height: 100vh" id="bacgr">
<main role="main" class="container d-flex justify-content-center">
<div class="starter-template">
<h1>Bootstrap starter template</h1>
<p class="lead">Use this document as a way to quickly start any new project.<br> All you get is this text and a mostly barebones HTML document.</p>
</div>
</main>
</div>
I am using Bootstrap v3.2.0 for laying out 3 graphs created using Angular-nvD3. I am trying to render the page for printing. I have some modified CSS in the #media print rule. Everything renders properly for printing in Chrome, but the charts do not resize for printing in IE 11. I have tried to trigger a window resize event in JavaScript, it executes but doesn't make any difference.
My div looks like this:
<div class="container">
<div class="row">
<div class="col-md-3 col-sm-3 col-xs-3">
<div ng-controller="BusinessPieChartController">
<h4>Business Allotment</h4>
<nvd3 options="options" data="data"></nvd3>
</div>
<div ng-controller="LocationTypePieChartController">
<h4>Location Types</h4>
<nvd3 options="options" data="data"></nvd3>
</div>
</div>
<div class="col-md-9 col-sm-9 col-xs-9">
<h4>Growth Over Time</h4>
<div ng-controller="HistoryLineAreaGraphController">
<nvd3 options="options" data="data"></nvd3>
</div>
</div>
</div>
</div>
Here is the JavaScript code I tried to no prevail.
var printTriggered = false;
var beforePrint = function () {
if (printTriggered) {
return
}
printTriggered = true;
setTimeout(function () {
printTriggered = false;
}, 2000)
var event
if (typeof Event === 'function') {
event = new Event('resize')
} else {
event = document.createEvent('Event')
event.initEvent('resize', true, true)
}
window.dispatchEvent(event)
};
if (window.matchMedia) {
var mediaQueryList = window.matchMedia('print');
mediaQueryList.addListener(function (mql) {
if (mql.matches) {
beforePrint();
}
});
}
window.onbeforeprint = beforePrint;
Here is how my graphs look from print preview in IE 11.
I shared this exact problem, although with just one graph. Ended up using duplicate elements for the graph.
First, one graph is rendered with width to match the paper size, and, once that's done, it's hidden, and another graph is shown instead:
<div class="graph-for-print"
ng-class="{rendered: vm.graphForPrintRendered}">
<nvd3 options="vm.graphOptions"
data="vm.graphData"></nvd3>
</div>
<div class="hidden-print"
ng-if="vm.graphForPrintRendered">
<nvd3 options="vm.graphOptions"
data="vm.graphData"></nvd3>
</div>
and the css
.graph-for-print {
max-width: 680px;
}
#media screen {
.graph-for-print.rendered {
overflow: hidden;
height: 0;
}
}
vm.graphForPrintRendered is true after a $timeout to ensure all digest cycles are done and the browser has had time to draw the chart.
Not pretty, but works.
I've been trying to use the react-scroll library with my HTML to be able to click on a cube i made up of divs in a wrap, scrolling down to another part of the page.
My react-scroll code is this:
var React = require('react');
var Scroll = require('react-scroll');
var Link = Scroll.Link;
var Element = Scroll.Element;
var Events = Scroll.Events;
var scroll = Scroll.animateScroll;
var scrollSpy = Scroll.scrollSpy;
var Section = React.createClass({
componentDidMount: function() {
scrollToElement(link1); {
let scroller = Scroll.scroller;
scroller.scrollTo(link1, {
duration: 1500,
delay: 100,
smooth: true,
},
)
}
},
///
render( < App / > , document.getElementById('app'));
I'm trying to scroll to this element in my HTML:
<Element name="link1">
<div class="bg2" id="snap1"></div>
</Element>
When one of these cubes are clicked:
<div class="cube" change-background colorcode=¨#f45642¨>
<div class="front"><span>Resume</span></div>
<div class="back"></div>
<div class="top"></div>
<div class="bottom"></div>
<div class="left"></div>
<div class="right"></div>
</div>
I made this fiddle https://jsfiddle.net/zhenkgxz/8/ but I'm new to JSfiddle so Im not sure if I have set it up correctly. Anyways, how can I get the scroll animation on click of the cube?
As the title suggests, I'm looking to have a little bit of jQuery - if an image is less than a defined width, it adds a class a certain element. This, for me, seems pretty easy but for some reason it's not working.
$(document).ready(function() {
var image = $('.work-each img');
if (image.width() < 500) {
$('.work-text').addClass('work-text-small');
}
});
This, should, add a class 'work-text-small' to the element 'work-text' if the image found under each .work-each is less than 500px.
Example of HTML (for each)
<div class="work-each">
<div>
<img src=""/>
<div class="work-text">
<p>Title</p>
<p>Text</p>
</div>
</div>
</div>
<div class="work-each">
<div>
<img src=""/>
<div class="work-text">
<p>Title</p>
<p>Text</p>
</div>
</div>
</div>
<div class="work-each">
<div>
<img src=""/>
<div class="work-text">
<p>Title</p>
<p>Text</p>
</div>
</div>
</div>
Thanks,
R
Use load instead, when DOM is ready only img tag is defined but the image isn't loaded yet. Its size comes when it's fully loaded
$(window).load(function () {
var image = $('.work-each img');
if (image.width() < 500) {
$('.work-text').addClass('work-text-small');
}
});
However as #rdck pointed if there are more images with class=".work-each img" code won't work so in that case you go trough each image and apply the class
$(window).load(function () {
var image = $('.work-each img');
image.each(function () {
var that = $(this);
if (that.width() < 500) {
that.next('div.work-text').addClass('work-text-small');
}
})
});
If you get dimensions using server code and set class accordingly, there would be no need to wait for image to load and css would immediately take effect as soon as html exists
i got a page on a site and there are several videos within blocs. When i play one video and then hit the close button or click on another box to open it, it works all just fine. But the problem comes when i add extra html markup around the videos, it breaks the close button behavior.
Here's the markup of a box (i've got multiples in my page):
<div class="box" data-size="660,605">
<div class="cunload2">
<div class="expandable">
<span class="simple">
<a class="cunload" href="javascript:;"></a>
</span>
<div class="exandable-vids-container">
<iframe ... ></iframe>
</div>
</div>
</div>
</div>
The cunload button is the one closing the box and unloading the video.
Here's the javascript (as seing at the vimeo api's page):
(function(){
var vimeoPlayers = document.querySelectorAll('iframe'), player;
for (var i = 0, length = vimeoPlayers.length; i < length; i++) {
player = vimeoPlayers[i];
$f(player).addEvent('ready', ready);
}
function addEvent(element, eventName, callback) {
if (element.addEventListener) { element.addEventListener(eventName, callback, false); }
else { element.attachEvent(eventName, callback, false); }
}
function ready(player_id) {
var container = document.getElementById(player_id).parentNode.parentNode,
froogaloop = $f(player_id),
apiConsole = container.querySelector('.console .output');
function setupSimpleButtons() {
var unloadBtn = container.querySelector('.simple').querySelector('.cunload');
addEvent(unloadBtn, 'click', function() { froogaloop.api('unload'); }, false);
}
setupSimpleButtons();
$(".cunload, .box:not(.expanded)").click(function(){
//if (!$(this).is('expanded')) {
froogaloop.api('unload');
//}
});
}
})();
This works just fine, but when i add an extra <div> around the iframe (and i really need to) it doesnt work anymore.
Any clue?
EDIT: problem is more complicated, i added an <ul> and <li> tags around the iframes as such:
<div class="box" data-size="660,605">
<div class="cunload2">
<div class="expandable">
<span class="simple">
<a class="cunload" href="javascript:;"></a>
</span>
<div class="exandable-vids-container">
<ul>
<li><iframe ... ></iframe></li>
<li><iframe ... ></iframe></li>
</ul>
</div>
</div>
</div>
</div>
and modified the js line :
var container = document.getElementById(player_id).parentNode.parentNode
to:
var container = document.getElementById(player_id).parentNode.parentNode.parentNode.parentNode
and i got it working.
The problem is that i use the <ul> and <li> tags to call jcarousel and that it adds an extra 3 divs between my .exandable-vids-container and the <ul>. Moreover, sometimes i'll call this carousel and sometimes not, so i really can't go with adding extras .parentNode in the js. This would have to be dynamic and i think the solution has to be in that direction.