This script's purpose is to load the data source into table first,
And then there is a search box to search data.
The dataSource only load at the first time page load,
How to make it reload the data source every 30 seconds, thanks
<TableSorter dataSource={"/welcome/get_winner_list"} config={CONFIG} />
Here's the whole script
/** #jsx React.DOM */
var CONFIG = {
sort: { column: "_id", order: "desc" },
filterText: "",
columns: {
_id: { name: "獎次"},
name: { name: "獎品"},
can_accept_prize_now: { name: "現領"},
staff_name: {name: "姓名"},
staff_id: {name: "工號"},
}
};
var TableSorter = React.createClass({
getInitialState: function() {
return {
items: this.props.initialItems || [],
sort: this.props.config.sort || { column: "", order: "" },
columns: this.props.config.columns,
filterText:this.props.config.filterText
};
},
componentWillMount: function() {
this.loadData(this.props.dataSource);
},
loadData: function(dataSource) {
if (!dataSource) return;
$.get(dataSource).done(function(data) {
console.log("Received data");
this.setState({items: data});
}.bind(this)).fail(function(error, a, b) {
console.log("Error loading JSON");
});
},
handleFilterTextChange: function (event){
this.setState({filterText:event.target.value})
},
editColumnNames: function() {
return Object.keys(this.state.columns);
},
receive_click:function(event){
name_staff=event.target.name.split(',')
dataSource='/take/'+name_staff[0]+'/'+name_staff[1];
$.getJSON(dataSource).done(function() {
console.log("Input success");
}.bind(this)).fail(function(error, a, b) {
console.log("Error :Input Prize");
});
itemsColumn=_.find(this.state.items,function(column){return column['_id']==name_staff[0]});
itemsColumn['taken_at']=true;
this.setState()
},
render: function() {
var rows = [];
var columnNames = this.editColumnNames();
var filters = {};
columnNames.forEach(function(column) {
var filterText = this.state.filterText;
filters[column] = null;
if (filterText.length > 0 ) {
filters[column] = function(x) {
if(x)
return (x.toString().toLowerCase().indexOf(filterText.toLowerCase()) > -1);
};
}
}, this);
var filteredItems = _.filter(this.state.items, function(item) {
return _.some(columnNames, function(c) {
return (!filters[c] || filters[c](item[c]));
}, this);
}, this);
var sortedItems = _.sortBy(filteredItems, this.state.sort.column);
if (this.state.sort.order === "desc") sortedItems.reverse();
var cell = function(x) {
return columnNames.map(function(c) {
if (c == 'taken_at') {
if (x[c])
return <td>
<span className="btn btn-shadow btn-danger" disabled="disabled">已領取</span>
</td>;
else
return <td>
<button name={x['_id']+','+x['staff_id']} className="btn btn-shadow btn-success" onClick={this.receive_click}>未領取</button>
</td>;
}
else if (c == 'can_accept_prize_now') {
if (x[c] )
return <td>
<img src="/images/check.png"></img>
</td>;
else
return <td>
<img src="/images/cross.png"></img>
</td>;
}
else
return <td>{x[c]}</td>;
}, this);
}.bind(this);
sortedItems.forEach(function(item) {
rows.push(
<tr key={item.id}>
{ cell(item) }
</tr>
);
}.bind(this));
var header = columnNames.map(function(c) {
return <th >{this.state.columns[c].name}</th>;
}, this);
return (
<div className="table">
<form>
<fieldset>
<input type="text" name="s" id="s" placeholder="搜尋方式:部分工號、部分姓名、部分獎次,皆可查詢。 Eg: 林 or 726 "
value={this.state.value} onChange={this.handleFilterTextChange}/>
</fieldset>
</form>
<p/>
<table cellSpacing="0" className="table table-striped table-advance table-hover prizes">
<thead>
<tr>
{ header }
</tr>
</thead>
<tbody>
{ rows }
</tbody>
</table>
</div>
);
}
});
var QueryString = function () {
// This function is anonymous, is executed immediately and
// the return value is assigned to QueryString!
var query_string = {};
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
// If first entry with this name
if (typeof query_string[pair[0]] === "undefined") {
query_string[pair[0]] = pair[1];
// If second entry with this name
} else if (typeof query_string[pair[0]] === "string") {
var arr = [ query_string[pair[0]], pair[1] ];
query_string[pair[0]] = arr;
// If third or later entry with this name
} else {
query_string[pair[0]].push(pair[1]);
}
}
return query_string;
} ();
var App = React.createClass({
render: function() {
return (
<div>
<TableSorter dataSource={"/welcome/get_winner_list"} config={CONFIG} />
</div>
);
}
});
$( document ).ready(function() {
console.log( "ready!" );
if(document.getElementById("searchWinner")){
React.render(<App />, document.getElementById("searchWinner"));
}
});
Update
I got the Uncaught TypeError: Cannot read property 'interval' of null
by the following code
getInitialState: function() {
return {
interval: 5,
items: this.props.initialItems || [],
sort: this.props.config.sort || { column: "", order: "" },
columns: this.props.config.columns,
filterText:this.props.config.filterText
};
},
componentDidMount: function() {
setInterval(function() {
this.setState({
interval: this.state.interval + 1
});
}.bind(this), 1000);
},
componentWillMount: function() {
this.loadData(this.props.dataSource);
},
var App = React.createClass({
render: function() {
return (
<div>
<TableSorter key={this.state.interval} dataSource={"/welcome/get_winner_list"} config={CONFIG} />
</div>
);
}
});
I suppose TableSorter is external component, so I suggest to force component to re-render using key property from parent component. Something like
componentDidMount: function() {
setInterval(function() {
this.setState({
interval: this.state.interval + 1
});
}.bind(this), 1000);
},
render: function() {
return <TableSorter key={this.state.interval} dataSource={"/welcome/get_winner_list"} config={CONFIG} />
}
Minus is that will reset any state inside TableSorter (paging, selected rows) after interval.
i can use this script:
setInterval(function() {
alert("alert every 3 second");
}, 3000);
EXAMPLE
Related
Function 1 Which returns JSON array.
function allPlans()
{
var all_plans = {
'Option1' : {
'free':{status:true,plantext:"5 Per Month"},
'premium':{status:true,plantext:"Unlimited"},
'vip':{status:true,plantext:"5 Per Month"}
},
'Option2' : {
'free':{status:true,plantext:"Unlimited"},
'premium':{status:true,plantext:"Unlimited"},
'vip':{status:true,plantext:"Unlimited"}
},
'Option3' : {
'free':{status:true,plantext:"Unlimited"},
'premium':{status:true,plantext:"Unlimited"},
'vip':{status:true,plantext:"Unlimited"}
},
'Option4':{
'free':{status:true,plantext:"-"},
'premium':{status:true,plantext:"Full Access"},
'vip':{status:true,plantext:"Full Access"}
},
'Option5' : {
'free':{status:true,plantext:"-"},
'premium':{status:true,plantext:"3 Per Month"},
'vip':{status:true,plantext:"3 Per Month"}
},
'Option6' : {
'free':{status:true,plantext:"-"},
'premium':{status:true,plantext:"-"},
'vip':{status:true,plantext:"1 Portfolio"}
},
'Option7' : {
'free':{status:true,plantext:"-"},
'premium':{status:true,plantext:"-"},
'vip':{status:true,plantext:"1 Per Month"}
},
}
return all_plans;
}
Another function "rendercolumn()" to return plans view.
function rendercolumn()
{
const options = allPlans();
var isrowclass = false;
var getrowclass = "";
const plansMap = Object.keys(options).reduce((acc, title) => {
if (props.planname == 'free')
{
var plans = options[title]["free"];
}
else if(props.planname == 'premium')
{
var plans = options[title]["premium"];
}
else if(props.planname == 'vip')
{
var plans = options[title]["vip"];
}
Object.keys(plans).forEach(plan =>
{
if (!acc[plan])
{
acc[plan] = [];
}
if(isrowclass == true)
{
isrowclass = false;
getrowclass = plan_item_gray;
}
else
{
isrowclass = true;
getrowclass = plan_item;
}
acc[plan].push({
title,
status: plans.status,
text: plans.plantext,
rowclass: getrowclass,
})
});
return acc;
}, {})
return (
<div>
{Object.keys(plansMap).map(plan => (
<Column key={plan} data={plansMap[plan]} />
))}
</div>
)
}
After that called component "Column"
const Column = ({data}) => (
<div>
{data.map(option => (
<div className={option.rowclass}>{option.text}</div>
))}
</div>
)
And at the last I have called "{rendercolumn()}" function to display the data on view.
Now in all above code I'm getting rows as expected, but it showing details twice.
I'm getting result like:
I want result like:
What changes needs to be done in above code?
i'm trying to write a module in rivets.js.
When i create a component with another nested component, the model is not in sync.
I just cant figure.
How do i sync value of hash to be same in the parent and child component?
Thank you.
Here is the fiddle (pen): http://codepen.io/anon/pen/qNmNJO?editors=1010
rivets.formatters.log = (data) => {
console.log(data);
};
rivets.formatters.filter = (items, arg) => {
console.log(items);
items = items.filter((item) => {
return item[arg];
});
return items;
};
rivets.formatters.eq = (value, arg) => {
return value == arg;
};
rivets.formatters.gt = (value, arg) => {
return value > arg;
};
rivets.formatters.lt = (value, arg) => {
return value < arg;
};
function ItemList(attributes) {
this.data = attributes;
this.checkbox_change = function(e, data) {
data.data.hash++;
};
}
rivets.components['item-list'] = {
template: function() {
return `
<div class="dest_wrap" rv-each-destination="data.destinations">
<label>
<input data-type="country" rv-on-click="checkbox_change" rv-checked="destination.selected" type="checkbox">
{ destination.name }
</label>
{ data.hash | log }
<span rv-text="data.hash"></span>
</div>
`;
},
initialize: function(el, attributes) {
return new ItemList(attributes);
}
};
// https://github.com/whayler1/rivets-example
let model = {
hash: 0,
destination_tree: [{
name: 'Itálie',
selected: false,
id: 1
}, {
name: 'Chorvatsko',
selected: true,
id: 2
}, {
name: 'Bulharsko',
selected: true,
id: 3
}],
};
function DestinationPicker(attributes) {
this.data = attributes;
}
rivets.components['destination-picker'] = {
template: function() {
return `
<div>
<item-list
hash="data.hash"
destinations=".data.destinations"
level="'countries'"
/>
</div>
<input type="number" rv-value="data.hash">
<span rv-text="data.hash"></span>
`;
},
initialize: function(el, attributes) {
return new DestinationPicker(attributes);
}
};
window.rivets_view = rivets.bind($('destination-picker'), model); // K čemu mohou přistupovat elementy
<script src="https://cdnjs.cloudflare.com/ajax/libs/rivets/0.9.0/rivets.bundled.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<main class="row">
<destination-picker destinations="destination_tree" hash="hash"></destination-picker>
</main>
I have this following code
var SelectOption = React.createClass({
getInitialState: function() {
return {
data: []
};
},
handleemployeeChange: function() {
alert('sssss');
},
loadOptionfromServer: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
cache: false,
success: function(data) {
this.setState({
data: data
});
console.log(data);
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
componentDidMount: function() {
alert('sssss');
this.loadOptionfromServer();
//setInterval(this.loadCommentsFromServer, this.props.pollInterval);
},
render: function() {
return ( < SelectOptionList data = {
this.state.data
}
/>
);
}
});
var SelectOptionList = React.createClass({
render: function() {
var commentNodes = this.props.data.map(function(list) {
return ( < Addcontenttoselect id = {
list.emp_ide_id
}
option = {
list.emp_name
} >
< /Addcontenttoselect>
);
});
return ( < select id = "select1"
className = "form-control"
data - placeholder = "Basic Select2 Box"
onChange = {
this.handleemployeeChange
} > {
commentNodes
} < /select>
);
}
});
var Addcontenttoselect = React.createClass({
render: function() {
return ( < option value = "{this.props.id}" > {
this.props.option
} < /option>);
}
});
ReactDOM.render( < div className = "col-md-3" > < h3 > Select Employee to Review < /h3><SelectOption url="/appraisal / employeelist " pollInterval={70000} /></div>, document.getElementById('select-box'));
So this component creates a Select Tag in the browser , I want to take the Value of the selected option and Call another component which will create a Table from a data got from API
Any leads please let me know
Thanks
With react you have multiple ways to pass around data to your components, it depends heavily on the use and the complexity of your application.
If you have a lot of components which need to know about the state/data of another component you should look at application architectures like flux or redux. Facebooks Flux
For some applications a full data flow architecture can be overkill so it depends on how you design your components. A common pattern is to have one component who handles the state/interactivity of your application.
Your main component will hold all the business logic of your app and pass down functions to its child to e.g. change state.
You can read more about this here Facebook thinking react
I did a little fiddle which adresses your challenge:
Fiddle
var Select = React.createClass({
render: function() {
var selectOptions = this.props.options.map(function(optionData) {
return (
<option key={optionData.id} value={optionData.id}>
{optionData.name}
</option>
);
});
return (
<select
id="select1"
className="form-control"
placeholder="Basic Select2 Box"
onChange={this.props.onChange}
>
{ selectOptions }
</select>
);
}
});
var SelectApp = React.createClass({
// The main component holds the data
getInitialState: function() {
return {
data: [],
currentData: null
}
},
componentDidMount: function () {
this.loadOptions();
},
loadOptions: function () {
var _this = this;
return setTimeout(function() {
_this.setState({data: [
{
id: 1,
name: 'Foo Bar'
},
{
id: 2,
name: 'Bar Foo'
}
]});
}, 2000);
},
onChange: function (e) {
var employeeId = e.target.value,
_this = this,
mockedData = [
{
id: 1,
data: 'Good employee'
},
{
id: 2,
data: 'Not so good employee'
}
];
// Mocking an additional data fetch
setTimeout(function () {
var result = mockedData.find(function (employeeData) {
return (employeeData.id == employeeId);
});
_this.setState({
currentData: result
});
}, 2000);
},
renderResult: function () {
if (this.state.currentData) {
return (
<div>
<h4>Employee:</h4>
<p>{this.state.currentData.data}</p>
</div>
);
}
return;
},
render: function() {
return (
<div>
<div>
<h3> Select Employee to Review </h3>
<Select url={this.props.url} options={this.state.data} onChange={this.onChange}/>
</div>
{this.renderResult()}
</div>
);
}
});
ReactDOM.render(<SelectApp url="/appraisal / employeelist " pollInterval={70000} />, document.getElementById('container'));
Edit:
renderResult: function () {
if (this.state.currentData) {
return (
<loadUserAppraisal url="something" empid={this.state.currentData.id} />
);
}
React newbie alert!!
I'm getting this error:
Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of `resultTable`. See https://fb.me/react-warning-keys for more information.
As suggested in https://fb.me/react-warning-keys, I have added keys to parent elements, but I may be overlooking something. Please suggest what I'm doing wrong
var ResultTable = React.createClass({
displayName: 'resultTable',
propTypes: {
table: React.PropTypes.object.isRequired
},
getDefaultProps: function() {
return {
table: {
rows: [],
cols: [],
}
};
},
getInitialState: function() {
return {
table: {
rows: this.props.table.rows,
cols: this.props.table.cols,
}
};
},
handleChange: function(event) {
console.log('data changed');
this.setState({
table: event.target.value
});
},
getValue: function(bug, property) {
//console.log('property', property);
try {
property = property.split('.');
if (property.length === 3) {
return bug[property[0]][property[1]][property[2]];
}
if (property.length === 2) {
if (property[1] === 'tickets') {
return bug[property[0]][property[1]].join(',');
} else {
return bug[property[0]][property[1]];
}
}
if (property.length === 1) {
if (/(updatedAt|createdAt|fixedAt|shippedAt|closedAt)/.test(property)) {
// return $filter('date')(bug[property[0]], 'shortDate');
} else if (property[0] === 'clones') {
return bug.clones.join(', ');
} else {
return bug[property[0]];
}
}
} catch (e) {
return '';
}
},
order: function(event) {
// event.preventDefault();
var hash = event.target.attributes.value.value + '_';
if (event.target.attributes['data-reverse'].value === 'true') {
hash += 'desc';
angular.element('a#' + event.currentTarget.attributes.id.value).attr('data-reverse', 'false');
} else {
hash += 'asc';
angular.element('a#' + event.currentTarget.attributes.id.value).attr('data-reverse', 'true');
}
window.location.hash = hash;
//this.setState({table: {rows: this.props.table.rows, cols:this.props.table.cols}});
},
render: function() {
var that = this;
var columns = this.props.table.cols;
var rows = this.props.table.rows;
//console.log(this.props.table.cols);
var selectedColumns = _.filter(columns, 'selected', true);
var cols = selectedColumns.map(function(col, i) {
return React.DOM.th({
key: 'col-' + i,
className: col.cssClass,
}, React.DOM.a({
key: 'a-' + i,
id: 'a-' + i,
href: '#',
value: col.value,
'data-reverse': 'false',
onClick: that.order
}, col.name));
});
var header = React.DOM.thead(null, React.DOM.tr({
key: 'header'
}, cols));
var body = React.DOM.tbody(null, rows.map(function(bug, i) {
return React.DOM.tr({
key: bug.id
},
selectedColumns.map(function(column, j) {
return React.DOM.td({
key: j
}, that.getValue(bug, column.value));
}));
}));
return React.DOM.table({
key: 'table-body',
className: 'table table-striped table-condensed pull-left resultTable'
}, [header, body]);
}
});
My guess is the problem is with the last line:
return React.DOM.table({
key: 'table-body',
className: 'table table-striped table-condensed pull-left resultTable'
}, [header, body]);
You're passing the array [header, body] as the children, and items in arrays need to have keys; however, neither header nor body has a key property.
However, you shouldn't add keys to fix this; instead, simply pass the two elements as individual arguments instead of an array:
return React.DOM.table({
key: 'table-body',
className: 'table table-striped table-condensed pull-left resultTable'
}, header, body);
I have a to-do list made in HTML, CSS and JavaScript, and I want to show a button only if they are 0 elements unchecked remaining. I think that the code should contain the variable named "numRemaining". I have tried something in JQuery, but it was a total failure.
This is what I have tried:
$(".todo-checkbox").change(function(){
if($(".todo-checkbox:checked").length > 4){
$("#yourButton").show();
}
});
This is my code:
<html>
<head>
<link rel="stylesheet" href="tomo.css">
<title>TOMO</title>
</head>
<body>
<h1>TOMO</h1>
<center>
<div id="todo-app">
<label class="todo-label" for="new-todo">What do you have to do today?</label>
<input type="text" id="new-todo" class="todo-input" placeholder="english homework">
<ul id="todo-list" class="count-this"></ul>
<div id="todo-stats"></div>
</div>
<button onclick="myPrint()">Print</button>
</center>
<script type="text/x-template" id="todo-item-template">
<div class="todo-view">
<input type="checkbox" class="todo-checkbox" {checked}>
<span class="todo-content" tabindex="0">{text}</span>
</div>
<div class="todo-edit">
<input type="text" class="todo-input" value="{text}">
</div>
<a href="#" class="todo-remove" title="Remove this task">
<span class="todo-remove-icon"></span>
</a>
</script>
<script type="text/x-template" id="todo-stats-template">
<span class="todo-count">
<span class="todo-remaining">{numRemaining}</span>
<span class="todo-remaining-label">{remainingLabel}</span> left.
</span>
<a href="#" class="todo-clear">
Clear <span class="todo-done">{numDone}</span>
completed <span class="todo-done-label">{doneLabel}</span>
</a>
</script>
<script src="http://yui.yahooapis.com/3.18.1/build/yui/yui-min.js"></script>
<script>
YUI().use('event-focus', 'json', 'model', 'model-list', 'view', function (Y) {
var TodoAppView, TodoList, TodoModel, TodoView;
TodoModel = Y.TodoModel = Y.Base.create('todoModel', Y.Model, [], {
sync: LocalStorageSync('todo'),
toggleDone: function () {
this.set('done', !this.get('done')).save();
}
}, {
ATTRS: {
done: {value: false},
text: {value: ''}
}
});
TodoList = Y.TodoList = Y.Base.create('todoList', Y.ModelList, [], {
model: TodoModel,
sync: LocalStorageSync('todo'),
done: function () {
return this.filter(function (model) {
return model.get('done');
});
},
remaining: function () {
return this.filter(function (model) {
return !model.get('done');
});
}
});
TodoAppView = Y.TodoAppView = Y.Base.create('todoAppView', Y.View, [], {
events: {
'#new-todo': {keypress: 'createTodo'},
'.todo-clear': {click: 'clearDone'},
'.todo-item': {
mouseover: 'hoverOn',
mouseout : 'hoverOff'
}
},
template: Y.one('#todo-stats-template').getHTML(),
initializer: function () {
var list = this.todoList = new TodoList();
list.after('add', this.add, this);
list.after('reset', this.reset, this);
list.after(['add', 'reset', 'remove', 'todoModel:doneChange'],
this.render, this);
list.load();
},
render: function () {
var todoList = this.todoList,
stats = this.get('container').one('#todo-stats'),
numRemaining, numDone;
if (todoList.isEmpty()) {
stats.empty();
return this;
}
numDone = todoList.done().length;
numRemaining = todoList.remaining().length;
stats.setHTML(Y.Lang.sub(this.template, {
numDone : numDone,
numRemaining : numRemaining,
doneLabel : numDone === 1 ? 'task' : 'tasks',
remainingLabel: numRemaining === 1 ? 'task' : 'tasks'
}));
if (!numDone) {
stats.one('.todo-clear').remove();
}
return this;
},
add: function (e) {
var view = new TodoView({model: e.model});
this.get('container').one('#todo-list').append(
view.render().get('container')
);
},
clearDone: function (e) {
var done = this.todoList.done();
e.preventDefault();
this.todoList.remove(done, {silent: true});
Y.Array.each(done, function (todo) {
todo.destroy({remove: true});
});
this.render();
},
createTodo: function (e) {
var inputNode, value;
if (e.keyCode === 13) { // enter key
inputNode = this.get('inputNode');
value = Y.Lang.trim(inputNode.get('value'));
if (!value) { return; }
this.todoList.create({text: value});
inputNode.set('value', '');
}
},
hoverOff: function (e) {
e.currentTarget.removeClass('todo-hover');
},
hoverOn: function (e) {
e.currentTarget.addClass('todo-hover');
},
reset: function (e) {
var fragment = Y.one(Y.config.doc.createDocumentFragment());
Y.Array.each(e.models, function (model) {
var view = new TodoView({model: model});
fragment.append(view.render().get('container'));
});
this.get('container').one('#todo-list').setHTML(fragment);
}
}, {
ATTRS: {
container: {
valueFn: function () {
return '#todo-app';
}
},
inputNode: {
valueFn: function () {
return Y.one('#new-todo');
}
}
}
});
TodoView = Y.TodoView = Y.Base.create('todoView', Y.View, [], {
containerTemplate: '<li class="todo-item"/>',
events: {
'.todo-checkbox': {click: 'toggleDone'},
'.todo-content': {
click: 'edit',
focus: 'edit'
},
'.todo-input' : {
blur : 'save',
keypress: 'enter'
},
'.todo-remove': {click: 'remove'}
},
template: Y.one('#todo-item-template').getHTML(),
initializer: function () {
var model = this.get('model');
model.after('change', this.render, this);
model.after('destroy', function () {
this.destroy({remove: true});
}, this);
},
render: function () {
var container = this.get('container'),
model = this.get('model'),
done = model.get('done');
container.setHTML(Y.Lang.sub(this.template, {
checked: done ? 'checked' : '',
text : model.getAsHTML('text')
}));
container[done ? 'addClass' : 'removeClass']('todo-done');
this.set('inputNode', container.one('.todo-input'));
return this;
},
edit: function () {
this.get('container').addClass('editing');
this.get('inputNode').focus();
},
enter: function (e) {
if (e.keyCode === 13) {
Y.one('#new-todo').focus();
}
},
remove: function (e) {
e.preventDefault();
this.constructor.superclass.remove.call(this);
this.get('model').destroy({'delete': true});
},
save: function () {
this.get('container').removeClass('editing');
this.get('model').set('text', this.get('inputNode').get('value')).save();
},
toggleDone: function () {
this.get('model').toggleDone();
}
});
function LocalStorageSync(key) {
var localStorage;
if (!key) {
Y.error('No storage key specified.');
}
if (Y.config.win.localStorage) {
localStorage = Y.config.win.localStorage;
}
var data = Y.JSON.parse((localStorage && localStorage.getItem(key)) || '{}');
function destroy(id) {
var modelHash;
if ((modelHash = data[id])) {
delete data[id];
save();
}
return modelHash;
}
function generateId() {
var id = '',
i = 4;
while (i--) {
id += (((1 + Math.random()) * 0x10000) | 0)
.toString(16).substring(1);
}
return id;
}
function get(id) {
return id ? data[id] : Y.Object.values(data);
}
function save() {
localStorage && localStorage.setItem(key, Y.JSON.stringify(data));
}
function set(model) {
var hash = model.toJSON(),
idAttribute = model.idAttribute;
if (!Y.Lang.isValue(hash[idAttribute])) {
hash[idAttribute] = generateId();
}
data[hash[idAttribute]] = hash;
save();
return hash;
}
return function (action, options, callback) {
var isModel = Y.Model && this instanceof Y.Model;
switch (action) {
case 'create': // intentional fallthru
case 'update':
callback(null, set(this));
return;
case 'read':
callback(null, get(isModel && this.get('id')));
return;
case 'delete':
callback(null, destroy(isModel && this.get('id')));
return;
}
};
}
new TodoAppView();
});
</script>
<script>
function myPrint() {
window.print();
}
</script>
</body>
</html>
You can compare the number of checked boxes to the total number of boxes, like this:
var $boxes = $(".todo-checkbox");
$boxes.change(function() {
if ($boxes.filter(':checked').length == $boxes.length) {
$("#yourButton").show();
}
});