Merge "Add preliminary support for dynamic content js and css."

This commit is contained in:
Dirk Dougherty 2014-01-24 03:14:19 +00:00 committed by Android (Google) Code Review
commit 17d28f805e
8 changed files with 728 additions and 0 deletions

View File

@ -0,0 +1,371 @@
/* content layout */
.resource-widget.resource-flow-layout {
display: inline-block;
margin-right: -20px;
/* clearfix idiom */ }
.resource-widget.resource-flow-layout.col-1 {
width: 60px; }
.resource-widget.resource-flow-layout.col-2 {
width: 120px; }
.resource-widget.resource-flow-layout.col-3 {
width: 180px; }
.resource-widget.resource-flow-layout.col-4 {
width: 240px; }
.resource-widget.resource-flow-layout.col-5 {
width: 300px; }
.resource-widget.resource-flow-layout.col-6 {
width: 360px; }
.resource-widget.resource-flow-layout.col-7 {
width: 420px; }
.resource-widget.resource-flow-layout.col-8 {
width: 480px; }
.resource-widget.resource-flow-layout.col-9 {
width: 540px; }
.resource-widget.resource-flow-layout.col-10 {
width: 600px; }
.resource-widget.resource-flow-layout.col-11 {
width: 660px; }
.resource-widget.resource-flow-layout.col-12 {
width: 720px; }
.resource-widget.resource-flow-layout.col-13 {
width: 780px; }
.resource-widget.resource-flow-layout.col-14 {
width: 840px; }
.resource-widget.resource-flow-layout.col-15 {
width: 900px; }
.resource-widget.resource-flow-layout.col-16 {
width: 960px; }
.resource-widget.resource-flow-layout:after {
content: ".";
display: block;
height: 0;
clear: both;
visibility: hidden; }
* html .resource-widget.resource-flow-layout {
height: 1px; }
.resource-card {
/* stuff that applies to all cards */
display: -webkit-flex;
-webkit-transform: translateZ(0);
float: left;
position: relative;
margin-right: 20px;
margin-bottom: 20px;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.25);
opacity: 0.8;
overflow: hidden;
transition: 0.4s box-shadow ease, 0.4s opacity ease;
/* card templates */
/* specific cards and customizations */ }
.resource-card .photo {
position: relative;
background-color: #eee;
background-size: cover;
background-repeat: no-repeat;
background-position: 50% 50%; }
.resource-card.nophoto .photo:after {
content: '';
display: block;
position: absolute;
left: 20px;
top: 20px;
right: 20px;
bottom: 20px;
opacity: 0.2;
background-position: center center;
background-repeat: no-repeat;
background-size: contain; }
.resource-card .icon {
background-position: center center;
background-repeat: no-repeat;
background-size: contain;
opacity: 0;
transition: 0.4s ease; }
.resource-card:hover .icon {
opacity: 0.2; }
.resource-card:hover {
opacity: 1;
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.5); }
.resource-card.resource-card-youtube.nophoto .photo:after, .resource-card.resource-card-youtube .icon {
background-image: url(../images/card_video.png); }
.resource-card.resource-card-samples.nophoto .photo:after, .resource-card.resource-card-samples .icon {
background-image: url(../images/card_sample.png); }
.resource-card.resource-card-blog.nophoto .photo:after, .resource-card.resource-card-blog .icon {
background-image: url(../images/card_post.png); }
.resource-card.resource-card-training.nophoto .photo:after, .resource-card.resource-card-training .icon {
background-image: url(../images/card_training.png); }
.resource-card .resource-card-text {
color: #333333; }
.resource-card .title {
/*font-weight: 700;*/
font-family: 'Roboto Condensed'; }
.resource-card .subtitle {
font-family: 'Roboto Condensed';
text-transform: uppercase;
opacity: 0.3; }
.resource-card .abstract {
font-weight: 300;
font-family: 'Roboto'; }
.resource-card.resource-card-12x7 {
width: 700px;
height: 400px;
-webkit-flex-direction: column; }
.resource-card.resource-card-12x7 .photo {
-webkit-flex: 1 1 auto;
border-bottom: 1px solid #ddd; }
.resource-card.resource-card-12x7 .resource-card-text {
margin: 20px;
padding-right: 88px; }
.resource-card.resource-card-12x7 .icon {
position: absolute;
right: 20px;
bottom: 20px;
width: 48px;
height: 48px; }
.resource-card.resource-card-12x7 .title {
font-size: 36px;
line-height: 35px;
max-height: 70px;
text-overflow: ellipsis;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical; }
.resource-card.resource-card-12x7 .subtitle {
font-size: 18px;
line-height: 20px;
max-height: 20px;
text-overflow: ellipsis;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
max-height: 0;
margin-top: 0;
transition: 0.4s ease; }
.resource-card.resource-card-12x7:hover .subtitle {
margin-top: 10px;
max-height: 20px; }
.resource-card.resource-card-12x7 .abstract {
font-size: 18px;
margin-top: 0;
line-height: 25px;
max-height: 75px;
text-overflow: ellipsis;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
max-height: 0;
transition: 0.4s ease; }
.resource-card.resource-card-12x7:hover .abstract {
margin-top: 20px;
max-height: 75px; }
.resource-card.resource-card-8x6 {
width: 460px;
height: 340px;
-webkit-flex-direction: column; }
.resource-card.resource-card-8x6 .photo {
-webkit-flex: 1 1 auto;
border-bottom: 1px solid #ddd; }
.resource-card.resource-card-8x6 .resource-card-text {
margin: 20px;
padding-right: 88px; }
.resource-card.resource-card-8x6 .icon {
position: absolute;
right: 20px;
bottom: 20px;
width: 48px;
height: 48px; }
.resource-card.resource-card-8x6 .title {
font-size: 36px;
line-height: 35px;
max-height: 70px;
text-overflow: ellipsis;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical; }
.resource-card.resource-card-8x6 .subtitle {
font-size: 18px;
line-height: 20px;
max-height: 20px;
text-overflow: ellipsis;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
max-height: 0;
margin-top: 0;
transition: 0.4s ease; }
.resource-card.resource-card-8x6:hover .subtitle {
margin-top: 10px;
max-height: 20px; }
.resource-card.resource-card-8x6 .abstract {
font-size: 18px;
margin-top: 0;
line-height: 25px;
max-height: 75px;
text-overflow: ellipsis;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
max-height: 0;
transition: 0.4s ease; }
.resource-card.resource-card-8x6:hover .abstract {
margin-top: 20px;
max-height: 75px; }
.resource-card.resource-card-8x6 .icon {
width: 32px;
height: 32px; }
.resource-card.resource-card-8x6 .title {
font-size: 24px;
line-height: 25px;
max-height: 50px;
text-overflow: ellipsis;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical; }
.resource-card.resource-card-8x6 .abstract {
font-size: 16px;
margin-top: 10px;
line-height: 20px;
max-height: 60px;
text-overflow: ellipsis;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical; }
.resource-card.resource-card-8x6 .subtitle {
font-size: 16px;
line-height: 20px;
max-height: 20px;
text-overflow: ellipsis;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
max-height: 0;
margin-top: 0;
transition: 0.4s ease; }
.resource-card.resource-card-8x6:hover .subtitle {
margin-top: 10px;
max-height: 20px; }
.resource-card.resource-card-8x6 .abstract {
font-size: 16px;
margin-top: 0;
line-height: 20px;
max-height: 60px;
text-overflow: ellipsis;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
max-height: 0;
transition: 0.4s ease; }
.resource-card.resource-card-8x6:hover .abstract {
margin-top: 10px;
max-height: 60px; }
.resource-card.resource-card-6x4 {
width: 340px;
height: 220px;
-webkit-flex-direction: column; }
.resource-card.resource-card-6x4 .photo {
-webkit-flex: 1 1 auto;
border-bottom: 1px solid #ddd; }
.resource-card.resource-card-6x4 .resource-card-text {
margin: 10px;
padding-right: 26px; }
.resource-card.resource-card-6x4 .icon {
position: absolute;
right: 10px;
bottom: 10px;
width: 16px;
height: 16px; }
.resource-card.resource-card-6x4 .title {
font-size: 16px;
line-height: 20px;
max-height: 40px;
text-overflow: ellipsis;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical; }
.resource-card.resource-card-6x4 .subtitle {
font-size: 13px;
line-height: 15px;
max-height: 30px;
text-overflow: ellipsis;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
max-height: 0;
margin-top: 0;
transition: 0.4s ease; }
.resource-card.resource-card-6x4:hover .subtitle {
max-height: 30px; }
.resource-card.resource-card-6x4 .abstract {
display: none; }
.resource-card.resource-card-6x4 .abstract {
font-size: 13px;
margin-top: 0;
line-height: 15px;
max-height: 30px;
text-overflow: ellipsis;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
max-height: 0;
display: block;
transition: 0.4s ease; }
.resource-card.resource-card-6x4:hover .abstract {
margin-top: 10px;
max-height: 30px; }
.resource-card.resource-card-4x3 {
width: 220px;
height: 160px;
-webkit-flex-direction: column; }
.resource-card.resource-card-4x3 .photo {
-webkit-flex: 1 1 auto;
border-bottom: 1px solid #ddd; }
.resource-card.resource-card-4x3 .resource-card-text {
margin: 10px;
padding-right: 26px; }
.resource-card.resource-card-4x3 .icon {
position: absolute;
right: 10px;
bottom: 10px;
width: 16px;
height: 16px; }
.resource-card.resource-card-4x3 .title {
font-size: 16px;
line-height: 20px;
max-height: 40px;
text-overflow: ellipsis;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical; }
.resource-card.resource-card-4x3 .subtitle {
font-size: 13px;
line-height: 15px;
max-height: 30px;
text-overflow: ellipsis;
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
max-height: 0;
margin-top: 0;
transition: 0.4s ease; }
.resource-card.resource-card-4x3:hover .subtitle {
max-height: 30px; }
.resource-card.resource-card-4x3 .abstract {
display: none; }

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -0,0 +1,106 @@
function mergeArrays() {
var arr = arguments[0] || [];
for (var i = 1; i < arguments.length; i++) {
arr = arr.concat(arguments[i]);
}
return arr;
}
var ALL_RESOURCES = mergeArrays(
DESIGN_RESOURCES,
DISTRIBUTE_RESOURCES,
GOOGLE_RESOURCES,
GUIDE_RESOURCES,
SAMPLES_RESOURCES,
TOOLS_RESOURCES,
TRAINING_RESOURCES,
YOUTUBE_RESOURCES,
BLOGGER_RESOURCES
);
for (var i = 0; i < ALL_RESOURCES.length; i++) {
ALL_RESOURCES[i].index = i;
}
function mergeMaps() {
var allRes = {};
var offset = 0;
for (var i = 0; i < arguments.length; i++) {
var r = arguments[i];
for (var tag in r.map) {
allRes[tag] = allRes[tag] || [];
allRes[tag] = allRes[tag].concat(r.map[tag].map(function(i){ return ALL_RESOURCES[i + offset]; }));
}
offset += r.arr.length;
}
return allRes;
}
function setFromArray(arr) {
arr = arr || [];
var set = {};
for (var i = 0; i < arr.length; i++) {
set[arr[i]] = true;
}
return set;
}
function buildResourceLookupMap(resourceDict) {
var map = {};
for (var key in resourceDict) {
var dictForKey = {};
var srcArr = resourceDict[key];
for (var i = 0; i < srcArr.length; i++) {
dictForKey[srcArr[i].index] = true;
}
map[key] = dictForKey;
}
return map;
}
// Type lookups
var ALL_RESOURCES_BY_TYPE = {
'design': DESIGN_RESOURCES,
'distribute': DISTRIBUTE_RESOURCES,
'google': GOOGLE_RESOURCES,
'guide': GUIDE_RESOURCES,
'samples': SAMPLES_RESOURCES,
'tools': TOOLS_RESOURCES,
'training': TRAINING_RESOURCES,
'youtube': YOUTUBE_RESOURCES,
'blog': BLOGGER_RESOURCES
};
var IS_RESOURCE_OF_TYPE = buildResourceLookupMap(ALL_RESOURCES_BY_TYPE);
// Tag lookups
var ALL_RESOURCES_BY_TAG = mergeMaps(
{map:DESIGN_BY_TAG,arr:DESIGN_RESOURCES},
{map:DISTRIBUTE_BY_TAG,arr:DISTRIBUTE_RESOURCES},
{map:GOOGLE_BY_TAG,arr:GOOGLE_RESOURCES},
{map:GUIDE_BY_TAG,arr:GUIDE_RESOURCES},
{map:SAMPLES_BY_TAG,arr:SAMPLES_RESOURCES},
{map:TOOLS_BY_TAG,arr:TOOLS_RESOURCES},
{map:TRAINING_BY_TAG,arr:TRAINING_RESOURCES},
{map:YOUTUBE_BY_TAG,arr:YOUTUBE_RESOURCES},
{map:BLOGGER_BY_TAG,arr:BLOGGER_RESOURCES}
);
var IS_RESOURCE_TAGGED = buildResourceLookupMap(ALL_RESOURCES_BY_TAG);
// Language lookups
var ALL_RESOURCES_BY_LANG = {};
for (var i = 0; i < ALL_RESOURCES.length; i++) {
var res = ALL_RESOURCES[i];
var lang = res.lang;
if (!lang) {
continue;
}
ALL_RESOURCES_BY_LANG[lang] = ALL_RESOURCES_BY_LANG[lang] || [];
ALL_RESOURCES_BY_LANG[lang].push(res);
}
var IS_RESOURCE_IN_LANG = buildResourceLookupMap(ALL_RESOURCES_BY_LANG);

View File

@ -0,0 +1,244 @@
// Requires jd_tag_helpers.js and the data JS to be loaded.
$(document).ready(function() {
$('.resource-widget').each(function() {
initResourceWidget(this);
});
});
function initResourceWidget(widget) {
var $widget = $(widget);
var isFlow, isCarousel;
isFlow = $widget.hasClass('resource-flow-layout');
if (!isFlow) {
isCarousel = $widget.hasClass('resource-carousel-layout');
}
// find size of widget by pulling out its class name
var sizeCols = 1;
var m = $widget.get(0).className.match(/\bcol-(\d+)\b/);
if (m) {
sizeCols = parseInt(m[1], 10);
}
var opts = {
source: $widget.data('source'),
cardSizes: ($widget.data('cardsizes') || '').split(','),
maxResults: parseInt($widget.data('maxresults') || '100'),
itemsPerPage: $widget.data('itemsperpage'),
sortOrder: $widget.data('sortorder'),
query: $widget.data('query'),
collectionId: $widget.data('collectionid'),
sizeCols: sizeCols
};
// run the search for the set of resources to show
var resources = buildResourceList(opts);
if (isFlow) {
drawResourcesFlowWidget($widget, opts, resources);
}
}
function drawResourcesFlowWidget($widget, opts, resources) {
$widget.empty();
var cardSizes = opts.cardSizes || ['4x3'];
for (var i = 0; i < resources.length; i++) {
var resource = resources[i];
var cardSize = i >= cardSizes.length ? cardSizes[cardSizes.length - 1] : cardSizes[i];
cardSize = cardSize.replace(/^\s+|\s+$/,'');
var $card = $('<a>')
.addClass('resource-card resource-card-' + cardSize + ' resource-card-' + resource.type)
.attr('href', resource.url);
$('<img>')
.addClass('photo')
.attr('src', resource.image || '')
.appendTo($card);
var subtitle = resource.type;
if (resource.timestamp) {
var d = new Date(resource.timestamp);
// TODO: localize, humanize
subtitle = (1 + d.getMonth()) + '/' + d.getDate() + '/' + d.getFullYear() + ' on ' + subtitle;
}
$('<div>')
.addClass('resource-card-text')
.append($('<div>').addClass('icon'))
.append($('<div>').addClass('title').text(resource.title))
.append($('<div>').addClass('subtitle').text(subtitle))
.append($('<div>').addClass('abstract').text(resource.summary))
.appendTo($card);
$card.appendTo($widget);
}
$widget.find('.resource-card .photo').each(function() {
var src = $(this).attr('src');
if (!src) {
$(this).parents('.resource-card').addClass('nophoto');
$(this).replaceWith($('<div>')
.addClass('photo'));
} else {
$(this).replaceWith($('<div>')
.addClass('photo')
.css('background-image', 'url(' + $(this).attr('src') + ')'));
}
});
}
function buildResourceList(opts) {
var maxResults = opts.maxResults || 100;
switch (opts.source) {
case 'query':
var query = opts.query || '';
var expressions = parseResourceQuery(query);
var alreadyAddedResources = {};
var allResources = [];
for (var i = 0; i < expressions.length; i++) {
var clauses = expressions[i];
// build initial set of resources from first clause
var firstClause = clauses[0];
var resources = [];
switch (firstClause.attr) {
case 'type':
resources = ALL_RESOURCES_BY_TYPE[firstClause.value];
break;
case 'lang':
resources = ALL_RESOURCES_BY_LANG[firstClause.value];
break;
case 'tag':
resources = ALL_RESOURCES_BY_TAG[firstClause.value];
break;
}
resources = resources || [];
// use additional clauses to filter corpus
if (clauses.length > 1) {
var otherClauses = clauses.slice(1);
resources = resources.filter(getResourceMatchesClausesFilter(otherClauses));
}
// filter out resources already added
if (i > 1) {
resources = resources.filter(getResourceNotAlreadyAddedFilter(alreadyAddedResources));
}
allResources = allResources.concat(resources);
if (allResources.length > maxResults) {
break;
}
}
if (opts.sortOrder) {
var attr = opts.sortOrder;
var desc = attr.charAt(0) == '-';
if (desc) {
attr = attr.substring(1);
}
allResources = allResources.sort(function(x,y) {
return (desc ? -1 : 1) * (parseInt(x[attr], 10) - parseInt(y[attr], 10));
});
}
return allResources.slice(0, maxResults);
case 'related':
// TODO
break;
case 'collection':
// TODO
break;
}
}
function getResourceNotAlreadyAddedFilter(addedResources) {
return function(x) {
return !!addedResources[x];
};
}
function getResourceMatchesClausesFilter(clauses) {
return function(x) {
return doesResourceMatchClauses(x, clauses);
};
}
function doesResourceMatchClauses(resource, clauses) {
for (var i = 0; i < clauses.length; i++) {
var map;
switch (clauses[i].attr) {
case 'type':
map = IS_RESOURCE_OF_TYPE[clauses[i].value];
break;
case 'lang':
map = IS_RESOURCE_IN_LANG[clauses[i].value];
break;
case 'tag':
map = IS_RESOURCE_TAGGED[clauses[i].value];
break;
}
if (!map || (!!clauses[i].negative ? map[resource.index] : !map[resource.index])) {
return false;
}
}
return true;
}
function parseResourceQuery(query) {
// Parse query into array of expressions (expression e.g. 'tag:foo + type:video')
var expressions = [];
var expressionStrs = query.split(',') || [];
for (var i = 0; i < expressionStrs.length; i++) {
var expr = expressionStrs[i] || '';
// Break expression into clauses (clause e.g. 'tag:foo')
var clauses = [];
var clauseStrs = expr.split(/(?=[\+\-])/);
for (var j = 0; j < clauseStrs.length; j++) {
var clauseStr = clauseStrs[j] || '';
// Get attribute and value from clause (e.g. attribute='tag', value='foo')
var parts = clauseStr.split(':');
var clause = {};
clause.attr = parts[0].replace(/\s+/g,'');
if (clause.attr) {
if (clause.attr.charAt(0) == '+') {
clause.attr = clause.attr.substring(1);
} else if (clause.attr.charAt(0) == '-') {
clause.negative = true;
clause.attr = clause.attr.substring(1);
}
}
if (parts.length > 1) {
clause.value = parts[1].replace(/\s+/g,'');
}
clauses.push(clause);
}
if (!clauses.length) {
continue;
}
expressions.push(clauses);
}
return expressions;
}

View File

@ -55,6 +55,13 @@ else
</script>
<script src="<?cs var:toroot ?>assets/js/docs.js" type="text/javascript"></script>
<!-- RESOURCES LIBRARY -->
<script src="<?cs if:android.whichdoc != 'online' ?>http:<?cs /if ?>//androiddevdocs-staging.appspot.com/ytblogger_lists_unified.js" type="text/javascript"></script>
<script src="<?cs var:toroot ?>jd_lists_unified.js" type="text/javascript"></script>
<script src="<?cs var:toroot ?>assets/js/jd_tag_helpers.js" type="text/javascript"></script>
<link href="<?cs var:toroot ?>assets/css/resourcecards.css" rel="stylesheet" type="text/css" />
<script src="<?cs var:toroot ?>assets/js/resourcecards.js" type="text/javascript"></script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-5831155-1']);