I'm trying to use app-location in order to dynamically load articles with links to other articles and be able to use browser navigation to go back and forth between them, like you would on a normal website. My understanding of app-location is that it grabs the URL send to the browser from a link and updates its route value, allowing you to perform routing client-side. This is my first test "article", which loads fine:
<h1>Title header</h1>
<p>Here's a bunch of words and this one's <b>special</b></p>
<a id="content-link" href="/articles/test2.txt" on-tap="handleTap">link to another article</a>
test2.txt just has a p tag with some text in it.
That's what it looks like on initial load. That link on the bottom of the main section is the link I am talking about. My intent is that if I click that link, it will change the url, then app-location will grab that and change its route property, then my observer can clear the old "article", load the new one and insert it into the content area. So, because the a "new page" was loaded, I should be able to hit the browser back button to return to the above page.
However, when I click the link, it just loads the file as a raw text file and displays that: <p>A NEW PAGE GOT LOADED WOOOOOO</p>, p tags included. Obviously, I've misunderstood something, which is likely since I'm still very new to Polymer and this was meant to be a learning project. Can anyone find what I've done wrong here, or give me pointers on what I should do differently to get my idea working?
Here's my full element code:
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/iron-ajax/iron-ajax.html">
<link rel="import" href="../../bower_components/iron-pages/iron-pages.html">
<link rel="import" href="../../bower_components/app-route/app-*">
<dom-module id="AR_Website-app">
<template>
<style>
/*header*/
header {
display: block;
padding: 20px 0;
padding-left: 30px;
background-color: rgb(220, 60, 50);
}
p {
margin: 0;
font-family: Verdana, Geneva, sans-serif;
font-size: 30px;
animation: title-fadein 1s;
animation-fill-mode: forwards;
}
#keyframes title-fadein {
from {
text-shadow: none;
opacity:0;
}
to{
text-shadow: 0 0 2px black;
opacity:1;
}
}
/*content*/
table {
border-collapse: collapse;
width: 100%;
min-height: calc(100vw - 110px);
}
table td {
vertical-align: top;
padding: 0;
}
table td:nth-child(1) {
background-color: blue;
}
table td:nth-child(2) {
background-color: green;
padding: 10px;
}
table td:nth-child(3) {
background-color: red;
}
</style>
<app-location route="{{route}}"></app-location>
<app-route
route="{{route}}"
pattern="/:articles"
data="{{routeData}}"
tail="{{subroute}}">
</app-route>
<iron-ajax url="{{route}}" handle-as="text" on-response="handleRequest"></iron-ajax>
<header><p>The Title</p></header>
<table>
<tr>
<td width="10%"><div id="left-banner">
</div></td>
<td width="80%">
<div id="content">
</div>
</td>
<td width="10%"><div id="right-banner">
</div></td>
</tr>
</table>
</template>
<script>
Polymer({
is: 'AR_Website-app',
observers: [
'_routeChanged(route)'
],
attached: function (){
this.route = "/articles/test.txt"
//console.log("Page loaded, sending request for route "+this.route)
this.$$('iron-ajax').generateRequest();
},
_routeChanged: function(route) {
console.log("new route "+route+", sending request")
this.$$('iron-ajax').generateRequest();
},
handleRequest: function(event) {
//Remove existing html snippet
console.log("handling request")
while (this.$$('#content *') != null){
this.$$('#content').removeChild(this.$$('#content *'))
}
//Create new html code from received text
console.log(event.detail.response)
var div = document.createElement('div')
div.innerHTML = event.detail.response
for (x = 0; x < div.childNodes.length; x++){
var content = div.childNodes[x]
this.$$('#content').appendChild(content)
}
//Add event handlers for links
//this.listen(this.$$('#content-link'), 'tap', 'handleTap')
},
handleTap: function(event) {
//Cancel page load from link
//event.preventDefault();
//Request new html snippet
console.log("Loading "+this.$$('#content-link').href)
//this.set('route', this.$$('#content-link').href)
this.route = this.$$('#content-link').href
//this.$$('iron-ajax').generateRequest();
}
});
</script>
</dom-module>
Based on your code
App directory
app
- bower_components
- articles
-- a.txt
-- b.txt
- index.html
- my-app.html
index.html
<!doctype html>
<html>
<head>
<link rel='import' href='my-app.html'>
</head>
<body>
<my-app></my-app>
</body>
</html>
my-app.html
<link rel='import' href='bower_components/polymer/polymer.html'>
<link rel='import' href='bower_components/app-route/app-location.html'>
<link rel='import' href='bower_components/app-route/app-route.html'>
<link rel='import' href='bower_components/iron-ajax/iron-ajax.html'>
<dom-module id='my-app'>
<template>
<style>
header{display:block;padding:20px 0 20px 30px;background-color:#dc3c32}p{margin:0;font-family:Verdana,Geneva,sans-serif;font-size:30px;animation:title-fadein 1s;animation-fill-mode:forwards}#keyframes title-fadein{from{text-shadow:none;opacity:0}to{text-shadow:0 0 2px #000;opacity:1}}table{border-collapse:collapse;width:100%;min-height:calc(100vw - 110px)}table td{vertical-align:top;padding:0}table td:nth-child(1){background-color:#00f}table td:nth-child(2){background-color:green;padding:10px}table td:nth-child(3){background-color:red}
</style>
<app-location route='{{route}}'></app-location>
<app-route
route='{{route}}'
pattern='/articles/:article'
data='{{routeData}}'>
</app-route>
<iron-ajax url='/articles/[[routeData.article]]' handle-as='text' on-response='handleRequest'></iron-ajax>
<header>
<p>The Title</p>
</header>
<table>
<tr>
<td width='10%'><div id='left-banner'></div></td>
<td width='80%'>
<div id='content'>
<div>[[article]]</div>
<a href='/articles/a.txt'>a article</a>
<a href='/articles/b.txt'>b article</a>
</div>
</td>
<td width='10%'><div id='right-banner'></div></td>
</tr>
</table>
</template>
<script>
Polymer({
is: 'my-app',
observers: [
'routeChanged(route)'
],
routeChanged: function (route) {
if (this.$$('app-route').active)
this.$$('iron-ajax').generateRequest();
},
handleRequest: function (event) {
this.article = event.detail.response;
}
});
</script>
</dom-module>
It start from app-location grab the url, update route, and that will trigger app-route, app-route try to match that url with pattern and set result to routeData, url on iron-ajax will change accordingly.
When you click on a href, url will change without reload because when iron-location active it will intercept clicks on links within your site ( see in links section and app-location use iron-location) so you don't need to anything with a href. After that routeChanged will be triggered and generate the request.
Beside, I saw you use
this.route = 'some path';
I think it should be
this.set('route.path', 'some path');
I hope this will help.
Related
I have created a webcomponent for a generic input boxes that i needed across multiple projects.
the design functionality remains same only i have to use switch themes on each projects.so i have decided to go on with webcomponents.One of the projects is based on Vue Js.In Vue js the DOM content is re-rendered while each update for enabling reactivity. That re-rendering of vue template is reinitializing my custom webcomponent which will result in loosing all my configurations i have assigned to the component using setters.
I know the below solutions. but i wanted to use a setter method.
pass data as Attributes
Event based passing of configurations.
Using Vue-directives.
using v-show instead of v-if
-- Above three solutions doesn't really match with what i am trying to create.
I have created a sample project in jsfiddle to display my issue.
Each time i an unchecking and checking the checkbox new instances of my component is creating. which causes loosing the theme i have selected. (please check he active boxes count)
For this particular example i want blue theme to be displayed. but it keep changing to red
JSFiddle direct Link
class InputBox extends HTMLElement {
constructor() {
super();
window.activeBoxes ? window.activeBoxes++ : window.activeBoxes = 1;
var shadow = this.attachShadow({
mode: 'open'
});
var template = `
<style>
.blue#iElem {
background: #00f !important;
color: #fff !important;
}
.green#iElem {
background: #0f0 !important;
color: #f00 !important;
}
#iElem {
background: #f00;
padding: 13px;
border-radius: 10px;
color: yellow;
border: 0;
outline: 0;
box-shadow: 0px 0px 14px -3px #000;
}
</style>
<input id="iElem" autocomplete="off" autocorrect="off" spellcheck="false" type="text" />
`;
shadow.innerHTML = template;
this._theme = 'red';
this.changeTheme = function(){
this.shadowRoot.querySelector('#iElem').className = '';
this.shadowRoot.querySelector('#iElem').classList.add(this._theme);
}
}
connectedCallback() {
this.changeTheme();
}
set theme(val){
this._theme = val;
this.changeTheme();
}
}
window.customElements.define('search-bar', InputBox);
<!DOCTYPE html>
<html>
<head>
<title>Wrapper Component</title>
<script src="https://unpkg.com/vue"></script>
<style>
html,
body {
font: 13px/18px sans-serif;
}
select {
min-width: 300px;
}
search-bar {
top: 100px;
position: absolute;
left: 300px;
}
input {
min-width: 20px;
padding: 25px;
top: 100px;
position: absolute;
}
</style>
</head>
<body>
<div id="el"></div>
<!-- using string template here to work around HTML <option> placement restriction -->
<script type="text/x-template" id="demo-template">
<div>
<div class='parent' contentEditable='true' v-if='visible'>
<search-bar ref='iBox'></search-bar>
</div>
<input type='checkbox' v-model='visible'>
</div>
</script>
<script type="text/x-template" id="select2-template">
<select>
<slot></slot>
</select>
</script>
<script>
var vm = new Vue({
el: "#el",
template: "#demo-template",
data: {
visible: true,
},
mounted(){
let self = this
setTimeout(()=>{
self.$refs.iBox.theme = 'blue';
} , 0)
}
});
</script>
</body>
</html>
<div class='parent' contentEditable='true' v-if='visible'>
<search-bar ref='iBox'></search-bar>
</div>
<input type='checkbox' v-model='visible'>
Vue's v-if will add/remove the whole DIV from the DOM
So <search-bar> is also added/removed on every checkbox click
If you want a state for <search-bar> you have to save it someplace outside the <search-bar> component:
JavaScript variable
localStorage
.getRootnode().host
CSS Properties I would go with this one, as they trickle into shadowDOM
...
...
Or change your checkbox code to not use v-if but hide the <div> with any CSS:
display: none
visibility: hidden
opacity: 0
move to off screen location
height: 0
...
and/or...
Managing multiple screen elements with Stylesheets
You can easily toggle styling using <style> elements:
<style id="SearchBox" onload="this.disabled=true">
... lots of CSS
... even more CSS
... and more CSS
</style>
The onload event makes sure the <style> is not applied on page load.
activate all CSS styles:
(this.shadowRoot || document).getElementById("SearchBox").disabled = false
remove all CSS styles:
(this.shadowRoot || document).getElementById("SearchBox").disabled = true
You do need CSS Properties for this to work in combo with shadowDOM Elements.
I prefer native over Frameworks. <style v-if='visible'/> will work.. by brutally removing/adding the stylesheet.
Is it possible for webpage to dynamically insert data from another file without needing a server call?
What I mean by that is can a .html page update itself with something like XMLHttpRequest but instead of this making a call to a server just simply read in a file that is the same location as the html page.
Pseudocode
if(userclicks on x)
{
read and display contents of y within this div)
}
Background
I am converting an html report that currently uses a frameset divided into left and right panels. The left panel lists a series of folders that have been processed, the right-hand side shows the processing done on the selected folder.
I need to remove framset because outdated and not supported in html 5
iFrames not a suitable alternative as they are not designed for showing the content of an integral part of the site, they look plain weird when this is done.
It is not viable to preload all the content of the page and then uses javascript to hide/show the content of the file when user changes selection because the single html file would be too large and too slow to load.
It is not viable to make a call to a server because there is no server, the reports are created by an application and then can be viewed standalone without the application being run. They can also be sent to support to be viewed standalone.
My temporary solution is that when the user selects a file then the processing html file is displayed in a new tab (or window), but there is not a very satisfactory for the user
If I'm reading your question right, all of the necessary data is part of the page at the outset (since you can't load it from a server, it has to all already be there — but see under the line below for more on that). But you've said:
It is not viable to preload all the content of the page and then uses javascript to hide/show the content of the file when user changes selection because the single html file would be too large and too slow to load.
So that suggests the data itself is quite a bit smaller than the representation of the data.
You can certainly have an element on the page (for instance, a div) that you update with a rendering of a subset of the data the page holds, using the DOM. Here's a trivial example:
const data = [
{label: "one", a: "a one", b: "b one", c: "c one"},
{label: "two", a: "a two", b: "b two", c: "c two"},
{label: "three", a: "a three", b: "b three", c: "c three"},
{label: "four", a: "a four", b: "b four", c: "c four"}
];
function populateMenu() {
const menu = document.getElementById("menu");
for (let i = 0; i < data.length; ++i) {
const entry = data[i];
const a = document.createElement("a");
a.href = `#entry-${i}`;
a.textContent = entry.label;
a.addEventListener("click", event => {
event.preventDefault();
showEntry(entry);
});
menu.appendChild(a)
}
}
function showEntry(entry) {
const content = document.getElementById("content");
const {a, b, c} = entry;
content.textContent = `a: ${a}, b: ${b}, c: ${c}`;
}
populateMenu();
#menu a {
padding: 4px;
}
<div id="menu"></div>
<div id="content"></div>
That uses ES2015+ syntax, but you can do the same thing with ES5 only if you need to for your target environments.
The content div there can, of course, be the majority of the page display.
This is the basic nature of a single-page application (SPA), so further research using that term may be useful. But your SPA is standalone (whereas most will do server calls, but still update the page as above).
In a comment you've said:
Currently the files are created at the outset, there is the main folder and a file that represents the processing of each folder. The user could have processed a 1000 folders so that means the main file is essentially a list of 1000 folders, and then there are a 1000 other files each containing a few pages of data. SO clearly if we to combine of all of this into one file it would be about 1000 time larger, yet user would only eve be viewing the procesing associated with one folder...So your approach above would not work for me.
I'm afraid you're trying to have your cake and eat it. :-) Either you can load the data later, or it's all on the page at the outset. You said in the question you can't load the data later, so it must be in the page at the outset.
But: Your use of the word "files" above suggests that this report without a server can be a set of files, not just a single file.
Your cross-browser options if HTML File A needs to load content from HTML File B are:
Use iframes and update the src to go from file to file. You've said in the question that they "aren't for the main content of the page", but that's not my understanding; and that they're ugly, but they're completely stylable via CSS. They can literally be seamlessly integrated into the main page.
Keep using frames, update the src of the frame to move from file to file. Yes, frames were removed in HTML5. They will never be removed from web browsers, too much legacy.
Sadly, you can't reliably use XMLHttpRequest when your page is loaded from a file: URL. Some browsers allow it, others don't. (You can't use fetch in any of them, it specifically doesn't support the file: scheme.)
Your constraints literally constrain your choices, I'm afraid.
Here's an iframe example:
report.html:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>Report</title>
<style>
#menu a {
padding: 4px;
}
#content {
border: none;
}
</style>
</head>
<body>
<div id="menu">
File 1
File 2
File 3
</div>
<iframe id="content" src="file1.html"></iframe>
<script>
document.getElementById("menu").addEventListener("click", event => {
event.preventDefault();
const a = event.target.closest("a");
document.getElementById("content").src = a.getAttribute("data-file");
});
</script>
</body>
</html>
file1.html (file2.html and file3.html are identical, just different names and numbers):
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>File 1</title>
</head>
<body>
This is file 1.
</body>
</html>
<template>
If you have local content on a file try using an <iframe> or a <template>. The latter is what we will consider. A <template> is inert and ignored by the browser so no matter how huge your extra content is -- it shouldn't be an issue.
Demo
<!DOCTYPE html>
<html>
<head>
<title>Page 1</title>
<style>
html {
font: 400 16px/1.5 'Consolas';
background: #000;
color: #fc0;
}
fieldset {
border-color: goldenrod;
border-radius: 8px;
}
input,
output {
display: block;
font: inherit;
}
[type=submit] {
float: right;
background: none;
color: gold;
border: 1px solid gold;
border-radius: 4px;
margin-top: 4px;
cursor: pointer;
}
</style>
</head>
<body>
<form id='import'>
<fieldset>
<legend>Import data.html by <b>XMLHttpRequest()</b></legend>
<output id='content'></output>
</fieldset>
<input type="submit">
</form>
<template id='data'>
<style>{margin: 30px auto}table{table-layout: fixed;border: 3px solid cyan;width: 99%;border-radius: 6px}caption{font-size:1.2rem;color:gold}th{width: 33%;background: rgba(0,11,187,0.3);border: 1px solid rgba(0,11,187,0.7);color:#fc3}td{min-height: 30px;border: 2px ridge cornflowerblue;;color: yellow;background: none}
</style><section><table><caption>DATA</caption><thead><tr><th>TH</th><th>TH</th><th>TH</th></tr></thead><tbody><tr><td>TD</td><td>TD</td><td>TD</td></tr><tr><td>TD</td><td>TD</td><td>TD</td></tr><tr><td>TD</td><td>TD</td><td>TD</td></tr></tbody></table></section>
</template>
<script>
document.forms.import.onsubmit = getContent;
function getContent(e) {
e.preventDefault();
const destination = document.querySelector('#content');
const template = document.querySelector('#data');
const clone = document.importNode(template.content, true);
destination.appendChild(clone);
}
</script>
</body>
</html>
XMLHttpRequest()
Assuming that a separate web page on the same domain as the target web page is feasible it is possible to import HTML from another webpage (whether from a server or same domain) using XMLHttpRequest().
Demo Outline
Main page: index.html, Imported page: data.html
On main page the element that will have the imported HTML needs this:
<div data-x="data.html"...
Any type of element assigned data-x attribute with the value of the imported web page's URL.
Plunker
index.html
This Stack Snippet does not function because it loads an external page, for a working demo review this Plunker
<!DOCTYPE html>
<html>
<head>
<title>Page 1</title>
<style>
html {
font: 400 16px/1.5 'Consolas';
background: #000;
color: #fc0;
}
fieldset {
border-color: goldenrod;
border-radius: 8px;
}
input,
output {
display: block;
font: inherit;
}
[type=submit] {
float: right;
background: none;
color: gold;
border: 1px solid gold;
border-radius: 4px;
margin-top: 4px;
cursor: pointer;
}
</style>
</head>
<body>
<form id='import'>
<fieldset>
<legend>Import data.html by <b>XMLHttpRequest()</b></legend>
<output data-x="data.html"></output>
</fieldset>
<input type="submit">
</form>
<script>
function xhr(e) {
e.preventDefault();
const tags = document.querySelectorAll("*");
let clone, file, xh;
for (let i = 0; i < tags.length; i++) {
if (tags[i].dataset.x) {
clone = tags[i].cloneNode(false);
file = tags[i].dataset.x;
xh = new XMLHttpRequest();
xh.onreadystatechange = function() {
if (xh.readyState == 4 && xh.status == 200) {
clone.innerHTML = xh.responseText;
tags[i].parentNode.replaceChild(clone, tags[i]);
xhr();
}
};
xh.open("GET", file, true);
xh.send();
return;
}
}
}
document.forms.import.addEventListener('submit', xhr);
</script>
</body>
</html>
data.html
This is just the plain web page that is imported to index.html, for a working demo, review this Plunker
<style>
section {
margin: 30px auto;
}
table {
table-layout: fixed;
border: 3px solid cyan;
width: 99%;
border-radius: 6px;
}
caption {
font-size:1.2rem;
color:gold;
}
th {
width: 33%;
background: rgba(0,11,187,0.3);
border: 1px solid rgba(0,11,187,0.7);
color:#fc3;
}
td {
min-height: 30px;
border: 2px ridge cornflowerblue;;
color: yellow;
background: none;
}
</style>
<section>
<table>
<caption>DATA</caption>
<thead>
<tr>
<th>TH</th>
<th>TH</th>
<th>TH</th>
</tr>
</thead>
<tbody>
<tr>
<td>TD</td>
<td>TD</td>
<td>TD</td>
</tr>
<tr>
<td>TD</td>
<td>TD</td>
<td>TD</td>
</tr>
<tr>
<td>TD</td>
<td>TD</td>
<td>TD</td>
</tr>
</tbody>
</table>
</section>
console.log('Test Sourced');
var onReady2 = function() {
console.log('memory game doc ready');
//TODO Add your code below to attach your event listeners to functions
//hides the images when button is clicked
$("#revealHide").click(function() {
$('.cardImg').fadeToggle('fast');
});
$(".cardDiv").click(function() {
$(".cardImg").fadeIn('slow')
});
};
//shows the img when clicked on the black box
// on document ready run the onReady2 function
$(document).ready(onReady2);
// revealHide function hides and shows all cards
function revealHide() {
//TODO add your code here to get the desired functionality
}
// singleClickFunc function hides and shows an indivdual card
function singleClickFunc() {
//TODO add your code here to get the desired functionality
}
body {
background-color: LightCyan;
}
.cardDiv {
background-color: blue;
width: 150px;
height: 150px;
padding: 6px;
margin: 6px;
border-style: dashed;
float: left;
}
img {
width: 150px;
height: 150px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Assignment 6-3</title>
<script src="vendors/jquery.min.js" charset="utf-8"></script>
<script src="script.js" charset="utf-8"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div>
<button id="revealHide" type="button">Show/Hide</button>
</div>
<div class="cardDiv">
<img class="cardImg" id='cardOne' src="imgs/banana.png">
</div>
<div class="cardDiv">
<img class="cardImg" id='cardTwo' src="imgs/pear.png">
</div>
<div class="cardDiv">
<img class="cardImg" id='cardThree' src="imgs/orange.png">
</div>
<div class="cardDiv">
<img class="cardImg" id='cardFour' src="imgs/apple.png">
</div>
</body>
</html>
On line 15-17 I want to click on a blue box and only reveal that picture when I click on it
To show the .cardImg in a .cardDiv when you click on it, use $(this).find('.cardImg') to target the .cardImg in that element instead of targeting all of them with $('.cardImg')
$(".cardDiv").on('click', function() {
$(this).find(".cardImg").fadeIn('slow')
});
replace $(".cardImg").fadeIn('slow') with $(this).find('img').fadeIn('slow')
console.log('Test Sourced');
var onReady2 = function() {
console.log('memory game doc ready');
//TODO Add your code below to attach your event listeners to functions
//hides the images when button is clicked
$("#revealHide").click(function() {
$('.cardImg').fadeToggle('fast');
});
$(".cardDiv").click(function() {
//$(".cardImg").fadeIn('slow')
$(this).find('img').fadeIn('slow')
});
};
//shows the img when clicked on the black box
// on document ready run the onReady2 function
$(document).ready(onReady2);
// revealHide function hides and shows all cards
function revealHide() {
//TODO add your code here to get the desired functionality
}
// singleClickFunc function hides and shows an indivdual card
function singleClickFunc() {
//TODO add your code here to get the desired functionality
}
body {
background-color: LightCyan;
}
.cardDiv {
background-color: blue;
width: 150px;
height: 150px;
padding: 6px;
margin: 6px;
border-style: dashed;
float: left;
}
img {
width: 150px;
height: 150px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Assignment 6-3</title>
<script src="vendors/jquery.min.js" charset="utf-8"></script>
<script src="script.js" charset="utf-8"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div>
<button id="revealHide" type="button">Show/Hide</button>
</div>
<div class="cardDiv">
<img class="cardImg" id='cardOne' src="imgs/banana.png">
</div>
<div class="cardDiv">
<img class="cardImg" id='cardTwo' src="imgs/pear.png">
</div>
<div class="cardDiv">
<img class="cardImg" id='cardThree' src="imgs/orange.png">
</div>
<div class="cardDiv">
<img class="cardImg" id='cardFour' src="imgs/apple.png">
</div>
</body>
</html>
Remember that $(".cardImg") is still a 'set' of matched elements, just like $(".cardDiv") is. If you do $(".cardImg").anythingAtAll() then you will perform the function on the entire set of matched elements, which is exactly the behavior you're describing. You want to add an event listener to each of your .cardDiv elements, so this part of your code is correct.
$(".cardDiv").click(function() {
});
Once inside of the function, you want to take an action on the 'specific element' that was clicked. You DO NOT want to take an action on the entire set of matched elements inside $('.cardImg'). So, instead of calling the fadeIn() function on that matched set, call it instead on the the specific element that was clicked. When inside the function, the keyword that gives you the specific element is this. Once you wrap the this keyword inside a jquery wrapper, $( ), like so $(this), you can then perform jquery functions on it, like fadeIn() and find() for example. find() will drilldown the DOM tree from the clicked element and find any elements that match whatever was passed in, in this case we pass in ".cardImg".
Your code should be:
$(".cardDiv").on('click', function() {
$(this).find(".cardImg").fadeIn('slow')
});
I'm new on WinJS development and I started with the WinJS tutorial. After updating my HTML and adding a WinJS.UI.SplitView I can't see the WinJS.UI.SplitViewCommands.
BTW when I toggle the pane I can't see the icons neither
Result
This is my code.
HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>WePin</title>
<!-- WinJS references -->
<link href="WinJS/css/ui-dark.css" rel="stylesheet" />
<script src="WinJS/js/base.js"></script>
<script src="WinJS/js/ui.js"></script>
<!-- WePin references -->
<link href="/css/default.css" rel="stylesheet" />
<script src="/js/default.js"></script>
</head>
<body class="win-type-body">
<div id="app" class="show-home">
<div class="splitView" data-win-control="WinJS.UI.SplitView">
<!-- Pane area -->
<div>
<div class="header">
<!--this is a button that allows you to "toggle" the menu in and out of view -->
<button class="win-splitviewpanetoggle" data-win-control="WinJS.UI.SplitViewPaneToggle"
data-win-options="{ splitView: select('.splitView') }"></button>
<div class="title">SplitView Pane area</div>
</div>
<!--this is where the navigation icons go -->
<div class="nav-commands">
<div data-win-control="WinJS.UI.SplitViewCommand" data-win-options="{
label: 'Alki Trail',
icon: 'mappin',
onclick: mySplitView.trailClicked
}"></div>
</div>
</div>
<!--/ Pane area-->
<!-- Content area -->
<div class="contenttext"><h2 class="win-h2">SplitView Content area</h2></div>
<!--/ Content area -->
</div>
</div>
</body>
</html>
CSS
.content,
#app {
height: 100%;
}
#app .win-splitviewpanetoggle {
float: left;
}
/* SplitView pane content style*/
#app .header {
white-space: nowrap;
}
#app .title {
font-size: 25px;
left: 50px;
margin-top: 6px;
vertical-align: middle;
display: inline-block;
}
#app .nav-commands {
margin-top: 20px;
}
#app .win-splitview-pane-closed .win-splitviewcommand-label {
/* Make sure pane content doesn't scroll if
SplitViewCommand label receives focus while pane is closed.
*/
visibility: hidden;
}
/*SplitView content style*/
#app .win-splitview-content {
background-color: rgb(112,112,112);
}
#app .contenttext {
margin-left: 20px;
margin-top: 6px;
}
Javascript
(function () {
"use strict";
var app = WinJS.Application;
var activation = Windows.ApplicationModel.Activation;
app.onactivated = function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
// TODO: This application has been newly launched. Initialize your application here.
} else {
// TODO: This application was suspended and then terminated.
// To create a smooth user experience, restore application state here so that it looks like the app never stopped running.
}
args.setPromise(WinJS.UI.processAll());
}
};
app.oncheckpoint = function (args) {
// TODO: This application is about to be suspended. Save any state that needs to persist across suspensions here.
// You might use the WinJS.Application.sessionState object, which is automatically saved and restored across suspension.
// If you need to complete an asynchronous operation before your application is suspended, call args.setPromise().
};
app.start();
})();
I had the same problem. Fixed by updating WinJS to latest version. Based on the changelog, SplitViewCommand is a new feature on WinJS v4.2
I've got a small page with two links that load content into a div dependant upon which link is pressed.
Question is fairly obvious, i'd like to highlight the current content link with a different color and toggle the color according to which link is pressed.
I'm attempting to do this with my current function using the following however it isn't working:
Pretty simply question so i'm obviously being dumb. Any help would be much appreciated.
Thanks!
<script type="text/javascript">
function loadContent(id) {
$("#video").load("streams.php?o="+id+"");
$('active').removeClass('active');
$(this).addClass('active');
}
</script>
Full code:
<html>
<head>
<title>beam</title>
<script type="text/javascript" src="swfobject.js"></script>
<script type="text/javascript">
swfobject.registerObject("myId", "9.0.0", "expressInstall.swf");
</script>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
function loadContent(id) {
$("#video").load("streams.php?o="+id+"");
$('active').removeClass('active');
$(this).addClass('active');
}
</script>
<style>
* { margin:0; padding:0; }
img{ border-style:none; }
html { height: 100%; }
body { height: 100%; font-family: "Tahoma", "Arial", sans-serif; font-size:15px; font-weight: bold;}
a {
color:#fff;
text-decoration: none;
}
.active {
color:#00d2ff;
}
.container {
position:absolute;
background:url("images/video-bg.jpg") no-repeat;
width:520px;
height:576px;
}
#video {
position:relative;
background:#000;
top:275px;
left:55px;
width:400px;
height:222px;
}
#stream-controller {
position:relative;
left:55px;
top:285px;
width:200px;
}
</style>
</head>
<body onLoad="loadContent(1);">
<div id="fb-root"></div>
<div class="container">
<div id="video">
</div>
<div id="stream-controller">
<p>STREAM 1 | STREAM 2</p>
</div>
</div>
</body>
</html>
One issue is your selector for the active link:
$('active').removeClass('active');
should be:
$('.active').removeClass('active');
The other issue, though I haven't tested this yet, is that I don't believe using href="javascript:loadContent(1);" will set the value of this in the function to the appropriate a element. If you're working with jQuery, you'd be better off setting the handler with jQuery, and passing the variable through the tag, something like:
<a class="stream active" href="streams.php?o=1">STREAM 1</a>
with the jQuery code:
$(function() {
$('a.stream').click(function(e) {
var $this = $(this);
$("#video").load($this.attr('href'));
$('.active').removeClass('active');
$this.addClass('active');
// prevent default link click
e.preventDefault();
})
});
Why don't you just do it in CSS?
a {
color:#fff;
text-decoration: none;
}
a:active {
color:#00d2ff;
}
editing out a part of my solution : ninja'd and a much better one from nrabinowitz
To toggle the "active" class to the link pressed, I would do this:
var $a = $("a");
$a.click(function() {
$a.removeClass("active");
$(this).addClass("active");
});