Serving Static Pages ember.js - ember.js

I'm currently retrofitting an old site and added ember. Previously when the user went products > product there was a link to a static page from there.
What's the best way to route to these static pages? (sellsheet in the object)
{
id: 32,
room: "String",
subroom: "String",
category: "String",
image: "Content/Images/Products/img.PNG",
name: "String",
description: "String",
bullets: [
{ content: "String" },
{ content: "String" },
{ content: "String" }
],
sellsheet: "Content/Sellsheets/conveyor.html"
}

I know this isn't the best way of doing it but it fit my needs.
I ended up just displaying the static page in an iframe at the bottom of the product page. Whenever you click view more, I hide the page with jQuery then show the iframe which gets the html loaded in through the anchor tag. Then I added a 'view less button' that hides the iframe and shows the page again.
HTML
<script type="text/x-handlebars" id="product">
<div id="valueprop-container">
<div class="centered">
<div class="col-left"><img {{bind-attr src=image}} /></div>
<div class="col-right">
<h2>{{{name}}}</h2>
<p>{{{description}}}</p>
<ul>
{{#each bullets}}
<li><span>{{{content}}}</span></li>
{{/each}}
</ul>
{{#if sellsheet}}
View More
{{/if}}
</div>
</div>
</div>
<div class="shadow"></div>
<div class="sellsheet">
<button class="expand">View Less</button>
<iframe name="frame" width="100%" height="100%" allowfullscreen style="position: absolute; border: none;"></iframe>
</div>
</script>
View
App.ProductView = Ember.View.extend({
didInsertElement: function(){
var productPage = $('#valueprop-container');
var sellSheet = $('.sellsheet');
$('.sell-sheet-click').click('on', function(){
productPage.hide();
sellSheet.show();
});
$('.sellsheet').click('on', function(){
productPage.show();
sellSheet.hide();
});
}
});

Related

Ember CRUD application

Hello I am trying to develop stock list data along with CRUD application for assignment purpose but only stock list data is getting displayed. Here is my code. Its not displaying the other part (i.e. CRUD part) and its not showing any error as well. I am very new to ember I think it might be some silly mistake but I've tried lot of stuff but I am lost as its not throwing any error. I am not looking or any backed neither I am planning to save data. I just want to show CRUD functionality of EMBER.js some thing like this of angular
Here is my HTML
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Ember.js</title>
<link rel="stylesheet" type="text/css" href="css/style.css" />
<!-- EmberJS dependencies -->
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="http://builds.handlebarsjs.com.s3.amazonaws.com/handlebars-v1.3.0.js"></script>
<script src="http://builds.emberjs.com/tags/v1.8.1/ember.min.js"></script>
<script src="http://builds.emberjs.com/tags/v1.0.0-beta.11/ember-data.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ember-localstorage-adapter/0.3.1/localstorage_adapter.js"></script>
<!-- Lightstreamer JavaScript Client library -->
<script src="http://cdnjs.cloudflare.com/ajax/libs/require.js/2.1.9/require.min.js"></script>
<script src="http://demos.lightstreamer.com/commons/lightstreamer.js"></script>
<!-- EmberJS code application -->
<script src="js/stockListDemoApp.js"></script>
<!-- Bootstrap -->
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.2.0/css/bootstrap.min.css">
</head>
<body>
<script type="text/x-handlebars" data-template-name="stock">
<div id="wrap">
<div id="top">
<a id="logoEmber" href="http://emberjs.com" target="_blank"><img src="images/ember_logo.png" alt="EMBERLOGO" hspace="0" border="0" /></a>
<div id="title">STOCK-LIST</div>
</div>
<table cellspacing="0" cellpadding="2" width="780" border="0" >
<thead>
<tr class="tableTitle">
<td>Name</td>
<td>Last</td>
<td>Time</td>
<td>Change</td>
<td>Bid Size</td>
<td>Bid</td>
<td>Ask</td>
<td>Ask Size</td>
<td>Min</td>
<td>Max</td>
<td>Ref.</td>
<td>Open</td>
</tr>
</thead>
<tbody>
{{#each item in model}}
<tr {{bind-attr class="item.isOdd:colOdd:colEven"}}>
<td><div {{bind-attr class="item.isOdd:stockNameOdd:stockNameEven"}}>{{item.stock_name}}</div></td>
<td>{{item.last_price}}</td>
<td>{{item.time}}</td>
<td>{{item.pct_change}}</td>
<td>{{item.bid_quantity}}</td>
<td>{{item.bid}}</td>
<td>{{item.ask}}</td>
<td>{{item.ask_quantity}}</td>
<td>{{item.min}}</td>
<td>{{item.max}}</td>
<td>{{item.ref_price}}</td>
<td>{{item.open_price}}</td>
</tr>
{{/each}}
</tbody>
</table>
<div class="disc">Simulated market data.</div>
</div>
</br>
</br>
<script type="text/x-handlebars" data-template-name="index">
<div class="jumbotron">
<h1>Welcome!</h1>
<p>This app demonstrates CRUD with validation in Ember.js</p>
</div>
</script>
<script type="text/x-handlebars" data-template-name="products">
<h1>Products</h1>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="products/index">
<table id="products_table" class="table">
<thead>
<tr>
<th>Name</th>
<th>Author</th>
<th>Price</th>
<th><button type="button" class="btn btn-default new-button" {{action "new"}}><span class="glyphicon glyphicon-plus"></span></button></th>
</tr>
</thead>
<tbody>
{{#each product in model}}
<tr {{bind-attr id=product.htmlID}}>
<td class="name">{{#link-to "products.show" product}}{{product.name}}{{/link-to}}</td>
<td class="author">{{product.author}}</td>
<td class="price">{{product.price}}</td>
<td class="action-buttons"><button type="button" class="btn btn-default edit-button" {{action "edit" product}}><span class="glyphicon glyphicon-pencil"></span></button>
<button type="button" class="btn btn-default delete-button" {{action "delete" product}}><span class="glyphicon glyphicon-remove"></button></td>
</tr>
{{/each}}
</tbody>
</table>
<p id="products_count">Total: {{controllers.products.productsCount}} products.</p>
</script>
<script type="text/x-handlebars" data-template-name="products/show">
<h2><span class="name">{{name}}</span></h2>
<p>By <span class="author">{{author}}</span></p>
<p><strong>$<span class="price">{{price}}</span></strong></p>
<p><span class="description">{{description}}</span></p>
<p class="action-buttons"><button type="button" class="btn btn-default edit-button" {{action "edit" model}}><span class="glyphicon glyphicon-pencil"></span></button>
<button type="button" class="btn btn-default delete-button" {{action "delete" model}}><span class="glyphicon glyphicon-remove"></button></p>
<p>{{#link-to 'products' class="index-link"}}Back to products index{{/link-to}}</p>
</script>
<script type="text/x-handlebars" data-template-name="products/edit">
<h2>{{#if isNew}}New{{else}}Edit{{/if}} Product</h2>
{{#form-for controller id="form-product" wrapper="bootstrap"}}
{{#input name}}
{{label-field name text="Product"}}
{{input-field name class="form-control" autofocus="true"}}
{{#if view.showError}}
{{error-field name}}
{{/if}}
{{/input}}
{{#input author}}
{{label-field author text="Author"}}
{{input-field author class="form-control"}}
{{#if view.showError}}
{{error-field author}}
{{/if}}
{{/input}}
{{#input description}}
{{label-field description text="Description"}}
{{input-field description class="form-control"}}
{{#if view.showError}}
{{error-field description}}
{{/if}}
{{/input}}
{{#input price}}
{{label-field price text="Price"}}
{{input-field price class="form-control"}}
{{#if view.showError}}
{{error-field price}}
{{/if}}
{{/input}}
<button type="submit" class="btn btn-primary save-button" {{action "save" model}}>Save</button>
{{#if isNew}}
<button type="button" class="btn btn-default cancel-button" {{action "delete" model}}>Cancel</button>
{{else}}
<button type="button" class="btn btn-default cancel-button" {{action "cancel" model}}>Cancel</button>
<button type="button" class="btn btn-danger delete-button" {{action "delete" model}}>Delete</button>
{{/if}}
{{/form-for}}
</script>
</script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/ember-data.js/1.0.0-beta.8/ember-data.min.js"></script>
<!-- ember-easyForm -->
<script src="http://builds.dockyard.com.s3.amazonaws.com/ember-easyForm/canary/shas/add6a40a68c8b081557a9011cf99ea255414e1b1/ember-easyForm.min.js"></script>
<!-- ember-validations -->
<script src="http://builds.dockyard.com.s3.amazonaws.com/ember-validations/canary/shas/2ff28c6ba4d227b0f863b327cdff23c381c37afb/ember-validations.min.js"></script>
</body>
</html>
and here is my app.js
App = Ember.Application.create();
App.ApplicationRoute = Ember.Route.extend({
model: function() {
return $.getJSON('https://ajax.googleapis.com/ajax/services/feed/load?' +
'v=1.0&num=50&q=https://news.google.com/news/feeds?output=rss&callback=?')
.then(function(data){
return data.responseData.feed.entries.map(function(entry){
var post = {};
post.title = entry.title;
return post;
});
});
}});
window.App = Ember.Application.create();
App.ApplicationAdapter = DS.FixtureAdapter.extend({
namespace: 'ember-crud'
});
Ember.EasyForm.Config.registerWrapper('bootstrap', {
formClass: '',
fieldErrorClass: 'has-error',
inputClass: 'form-group',
errorClass: 'help-block error',
hintClass: 'help-block',
labelClass: ''
});
App.Router.map(function() {
this.resource('products', function() {
this.route('new');
this.route('show', {path: '/:product_id'});
this.route('edit', {path: '/:product_id/edit'});
});
});
App.Product = DS.Model.extend(Ember.Validations.Mixin, {
name: DS.attr('string'),
author: DS.attr('string'),
description: DS.attr('string'),
price: DS.attr('number'),
// To identify html tag for a Product.
htmlID: function() {
return 'product' + this.get('id');
}.property('id'),
validations: {
name: {
presence: true
},
price: {
presence: true,
numericality: {
greaterThanOrEqualTo: 0
}
}
}
});
App.resetFixtures = function() {
App.Product.FIXTURES = [
{
id: 1,
name: 'Ember.js in Action',
author: 'Joachim Haagen Skeie',
description: 'Ember.js in Action is a crisp tutorial that introduces the Ember.js framework and shows you how to build production-quality web applications.',
price: 44.99
},
{
id: 2,
name: 'Building Web Applications with Ember.js',
author: 'Jesse Cravens & Thomas Brady',
description: 'This guide provides example-driven instructions on how to develop applications using Ember, one of the most popular JavaScript frameworks available.',
price: 29.99
},
{
id: 3,
name: 'The Ember.js Way',
author: 'Brian Cardarella & Alex Navasardyan',
description: "Inspired by Addison-Wesley's classic The Rails Way series, The Ember.js Way crystallizes all that's been learned about Ember.js development into a start-to-finish approach that works.",
price: 39.99
},
{
id: 4,
name: 'Instant Ember.JS Application Development: How-to',
author: 'Marc Bodmer',
description: 'A practical guide that provides you with clear step-by-step examples. The in-depth examples take into account the key concepts and give you a solid foundation to expand your knowledge and your skills.',
price: 20.69
}
];
};
App.resetFixtures();
App.ProductsRoute = Ember.Route.extend({
model: function() {
return this.store.find('product');
},
actions: {
// Redirect to new form.
new: function() {
this.transitionTo('products.new');
},
// Redirect to edit form.
edit: function(product) {
this.transitionTo('products.edit', product);
},
// Save and transition to /products/:product_id only if validation passes.
save: function(product) {
var _this = this;
product.validate().then(function() {
product.save();
_this.transitionTo('products.show', product);
});
},
// Roll back and transition to /products/:product_id.
cancel: function(product) {
product.rollback();
this.transitionTo('products.show', product);
},
// Delete specified product.
delete: function(product) {
product.destroyRecord();
this.transitionTo('products');
}
}
});
App.ProductsController = Ember.ArrayController.extend({
productsCount: function() {
return this.get('model.length');
}.property('#each')
});
App.ProductsIndexRoute = Ember.Route.extend({
model: function() {
return this.modelFor('products');
}
});
App.ProductsIndexController = Ember.ArrayController.extend({
needs: ['products'],
sortProperties: ['name']
});
App.ProductsEditRoute = Ember.Route.extend({
model: function(params) {
return this.store.find('product', params.product_id);
},
// Roll back if the user transitions away by clicking a link, clicking the
// browser's back button, or otherwise.
deactivate: function() {
var model = this.modelFor('products.edit');
if (model && model.get('isDirty') && !model.get('isSaving')) {
model.rollback();
}
}
});
App.ProductsNewRoute = Ember.Route.extend({
model: function() {
return this.store.createRecord('product');
},
isNew: true,
renderTemplate: function(controller, model) {
this.render('products.edit', {
controller: controller
});
},
// Roll back if the user transitions away by clicking a link, clicking the
// browser's back button, or otherwise.
deactivate: function() {
var model = this.modelFor('products.new');
if (model && model.get('isNew') && !model.get('isSaving')) {
model.destroyRecord();
}
}
});

Ember - Adding an extra action for #link-to

I have a simple Ember application where I have a dynamically generated list of links-to. On a single click per link, I show some detail about the clicked item.
I also want to add "ondblclick" event to the link-to. Is this at all possible? If not, I'm not attached to having link-to for single and double clicks.
I want to be able to keep the functionality I already have for the single-click event, and also add a double-click event (ideally, without firing a single-click event meanwhile ). I want to be able to store the double clicked titles and ids associated with them.
I tried using Ember.View object for this (commented out below), and I tried adding {{action "collectDoubleClicked" on="doubleClick"}} into the link-to, but that doesn't work. No luck so far.
Any help will be much appreciated.
Here is my HTML:
<script type="text/x-handlebars" data-template-name="application">
<div id="headerDiv">
<ul>
<li>
<image src="logo.png" style="width:439px;height:102px;"/>
</li>
<li>
{{#link-to 'home'}}Home{{/link-to}} | {{#link-to 'help'}}Help{{/link-to}}
</li>
</ul>
</div>
<div class="collections">
{{partial 'collections'}}
</div>
<div class="statistics">
{{outlet}}
</div>
</script>
<script type="text/x-handlebars" id="collections">
<div id='collectionsDiv'>
{{#each}}
{{#link-to 'item' this }} <!-- {{action "collectToSearch" on="doubleClick"}} -->
{{title}}
{{/link-to}}
{{/each}}
</div>
</script>
And my JavaScript:
App = Ember.Application.create();
App.Router.map(function () {
this.resource('home', {
path: '/'
});
this.resource('help');
this.resource('item', {
path: ':item_id'
});
});
App.ApplicationRoute = Ember.Route.extend({
model: function () {
return items;
}
});
var items = [{
id: 1,
title: 'Item 1',
contentType: 'Image',
description: 'description 1'
}, {
id: 2,
title: 'Item 2',
contentType: 'Text',
description: 'description 2'
}, {
id: 3,
title: 'Item 3',
contentType: 'Undefined',
description: 'description 3'
}];
App.ApplicationController = Ember.ArrayController.extend({
actions: {
collectDoubleClicked
function () {
console.log("collectToSearch: ", this.get('model.title'));
}
}
});
/**
App.Application = Ember.View.extend({
itemTitles: [items.length],
itemIds: [items.length],
itemCountDoubleClick: 0,
doubleClick: function (title, id) {
console.log("double click");
itemTitles[itemCountDoubleClick] = title;
itemIds[itemCountDoubleClick] = id;
itemCountDoubleClick++;
return false;
}
});
**/
You can try something like this:
{{#link-to 'item' this }}
<span {{action "doubleClickAction" on="doubleClick"}}>
{{title}}
</span>
{{/link-to}}
If my understand is true, span catch event before link.
But I think, we have more true way
I don't think there's a way to handle doubleClick without triggering singleClick. Have a look at this jsBin. Before doubleClick is even triggered, click was already triggered twice. I understand what you're trying to do and it makes sense.

Change a view property from an unrelated controller

I have the following view:
App.MessageTrayView = Bootstrap.AlertMessage.extend({
message: 'This is a message.',
});
Displayed in this template:
<script type="text/x-handlebars" data-template-name="nodes">
<article>
<form class="form-horizontal">
<fieldset>
{{view App.MessageTrayView id="message-tray-view"}}
<div id="legend" class="">
<legend class="">Nodes <span class="badge">{{controllers.nodesIndex.length}} records</span>
<div class="pull-right">
<a {{action destroyAllRecords}}><i class="icon-remove-circle"></i><a/>
{{#linkTo "nodes.new" class="btn btn-primary"}}Add Node{{/linkTo}}
</div>
</legend>
</div>
{{outlet}}
</fieldset>
</form>
</article>
</script>
And this unrelated controller:
App.NodesIndexController = Ember.ArrayController.extend({
destroyAllRecords: function () {
console.log('destroyAllRecords called');
App.MessageTrayView.set('message', 'All nodes have been deleted');
},
});
I want to change the message displayed as soon as the destroyAllRecords is triggered. This is not working (the error message in the console is telling me that I am doing something * very* wrong). How can I change the message property, so that the changes are directly visible on the page?
You can see the code live here
One quick way of doing this could be to define a property on the App namespace:
App = Ember.Application.create({
messageTrayContent: ''
});
then bind to it in your view using the suffix Binding after your property name:
App.MessageTrayView = Bootstrap.AlertMessage.extend({
messageBinding: 'App.messageTrayContent'
});
Now doing:
App.NodesIndexController = Ember.ArrayController.extend({
destroyAllRecords: function () {
console.log('destroyAllRecords called');
App.set('messageTrayContent', 'All nodes have been deleted');
},
});
should work.
Hope it helps.

Mark the current detail entry in a master list

I have a list of users which are displayed in a master view on the left side (Twitter Bootstrap CSS). Details of each user can be shown by clicking the show button. They will be displayed on the right side (detail).
How can I remove the show button for the currently displayed user? e.g. #/users/1 shouldn't render the show button for the first user.
index.html
<script type="text/x-handlebars" data-template-name="users">
<div class='row'>
<div class='span4'>
<table class='table table-striped'>
{{#each model}}
<tr>
<td>{{lastName}}</td>
<td>{{#linkTo 'user' this}}<button class="btn" type="button">show</button>{{/linkTo}}</td>
</tr>
{{/each}}
</table>
</div>
<div class='span8'>
{{outlet}}
</div>
</div>
</script>
<script type="text/x-handlebars" data-template-name="user">
<h1>{{firstName}} {{lastName}}</h1>
</script>
app.js
App = Ember.Application.create();
App.Store = DS.Store.extend({
revision: 12,
adapter: 'DS.FixtureAdapter'
})
App.Router.map(function() {
this.resource('users', function() {
this.resource('user', { path: ':user_id' })
})
});
App.UsersRoute = Ember.Route.extend({
model: function() {
return App.User.find();
}
});
App.User = DS.Model.extend({
firstName: DS.attr('string'),
lastName: DS.attr('string')
})
App.User.FIXTURES = [{
id: 1,
firstName: "Bill",
lastName: "Clinton"
}, {
id: 2,
firstName: "Barack",
lastName: "Obama"
}]
Ember provides some support for doing what you want. By default it sets the "active" css class on the selected element. You can find more information about that here: http://emberjs.com/api/classes/Ember.LinkView.html (note that the {{#linkTo}} is just a helper based on the LinkView).
The simplest way to override this behavior, since instead of "active" you want to hide the button, would be to make use of the hide class that comes with Twitter Bootstrap. So your users template would look like:
<script type="text/x-handlebars" data-template-name="users">
<div class='row'>
<div class='span4'>
<table class='table table-striped'>
{{#each model}}
<tr>
<td>{{lastName}}</td>
<td>{{#linkTo 'user' this activeClass="hide"}}<button class="btn" type="button">show</button>{{/linkTo}}</td>
</tr>
{{/each}}
</table>
</div>
<div class='span8'>
{{outlet}}
</div>
</div>
</script>
<script type="text/x-handlebars" data-template-name="user">
<h1>{{firstName}} {{lastName}}</h1>
</script>

Emberjs bindAttr inside of #each

Code for view is
Ember.View.extend({
template: Ember.Handlebars.compile(html), // html is in string
content: function() {
return [
{ Title: "Dashboard", ID: "dashboard" },
{ Title: "Invoices", ID: "invoices" },
{ Title: "Expenses", ID: "expenses" },
{ Title: "People", ID: "people" },
{ Title: "Reports", ID: "reports" },
{ Title: "Settings", ID: "settings" }
]},
iconClass: function(link){
return "icon icon-" + link.ID
}
});
Template (show above as "html") looks like this:
<ul>
{{#each link in view.content}}
<li>
<a>
<span class="icon" {{bindAttr class="view.iconClass(link)"}}></span>
<span class="title">{{link.Title}}</span>
</a>
</li>
{{/each}}
</ul>
This renders
<span class="icon" data-bindattr-2="2"></span>
So additional class attribute is not rendered. Am I doing something wrong with scope or?
NOTE:
I changed my code to show what I want to do.
EDIT
According to the new question, you'll have to use an Ember.CollectionView:
App.FooCollectionView = Ember.CollectionView.extend({
itemViewClass: Ember.View.extend({
iconClass: function() {
return "icon-dashboard icon " + this.get('content.ID');
}.property('content.ID')
})
});
As you can see, each itemViewClass has a property iconClass which depends on its content.id.
Now you'll have to add the collection view in the template of the view FooView:
<ul>
{{#collection App.FooCollectionView contentBinding="view.content"}}
<li>
<a>
<span {{bindAttr class="view.iconClass"}}>foo</span>
<span class="title">{{view.content.Title}}</span>
</a>
</li>
{{/collection}}
</ul>
Here we are using the {{collection}} Handlebars helper, and we bind the content of the FooView to the FooCollectionView.
It will automatically create an itemViewClass instance for each object in the CollectionView.content, set the its to the associated object, and add it to the view.
I suggest you to read the Ember.CollectionView documentation.
And you could try this solution in this JSFiddle.
For others who are having the problem with bindAttr resulting in something like:
data-bindattr-1="1"
make sure you are using
{{bindAttr src="myvariable"}}
instead of {{bindAttr src="{{myvariable}}"}}
Might save you some time searching for the answer, this was what caused my code not to work.
Another simple way to do this is to add a computed property to your model. In the example below I needed a specialized style atribute.
Model ----
App.Photo = Em.Object.extend(
objectId: null
url: ""
style: (->
"background-image:url('" + #get("url") + "')"
).property("url")
)
Template -----
{{#each item in App.photoController}}
<div {{bindAttr style="item.style"}}></div>
{{/each}}