afterRender not working, am I misinterpreting how it works? - javascript

this is my code:
<div data-bind="foreach : {data:movies}, afterRender: $parent.toggleHide ">
<div class="content-item full bottom-border">
<div class="content-item-container">
<div class="movie-listing-header">
<a class="icon arrow"></a>
<div class="movie-details">
<div class="title"></div>
<div class="info">
<div class="rating">
</div>
<div class="time" data-bind=" text: movieruntime "></div>
</div>
</div>
<a class="icon right-arrow" href="#" data-bind="attr: { href: DetailsUrl }"></a>
</div>
<div class="showtimes">
<div data-bind="template: { name: 'movie-grouped-showtimes-template', data: $data }"></div>
</div>
</div>
</div>
</div>
this is my .js in my viewModel
function TheatreViewModel(theatre) {
var self = this,
initialData = theatre || Regal.userPrimaryTheatre || {},
theatreServiceParams = {
tmsId: initialData.TmsId,
date: initialData.selectedDate || new Date()
};
self.TheatreName = initialData.TheatreName || '';
self.PhoneNumber = initialData.PhoneNumber || '';
self.selectedTheatreTms = initialData.TmsId;
self.theatre = ko.observable();
self.isLoading = ko.observable(false);
self.selectedDate = ko.observable(initialData.selectedDate || new Date());
self.filterFormats = [];
self.selectedFormat = ko.observable(Regal.allFormatsFilterItem);
self.filterFormats.push(Regal.allFormatsFilterItem);
if (Regal.movieFormats) {
var filtered = _.where(Regal.movieFormats, {
Filterable: true
});
_.forEach(filtered, function (f) {
f.enabled = ko.observable(false);
self.filterFormats.push(f);
});
}
self.addressText = ko.computed(function () {
var theat = ko.unwrap(self.theatre);
var addie;
if (!theat || theat && !theat.Address1) {
addie = initialData;
} else {
addie = theat;
}
return addie.Address1 + ', ' + addie.City + ' ' + addie.State + ' ' + addie.PostalCode;
});
self.mapEmbedUrl = ko.computed(function () {
var a = self.addressText();
return 'http://maps.google.com/maps?q=' + encodeURI(a);
});
self.movies = ko.computed(function () {
var thea = self.theatre(),
mov = ko.unwrap((thea || {}).Movies),
format = self.selectedFormat();
if (format && format !== Regal.allFormatsFilterItem) {
return _.filter(mov, function (m) {
return _.contains(_.pluck(m.formats(), 'Id'), format.Id);
});
}
return mov;
});
self.getPerformances = function () {
self.isLoading(true);
Regal.loadTheatre(self.selectedDate(), self.selectedTheatreTms,
function (data) {
self.isLoading(false);
if (data) {
var allFmts = _.uniq(_.flatten(_.map(ko.unwrap(data.Movies), function (mov) {
return mov.formats();
})));
_.forEach(allFmts, function (fmt) {
var filt = _.findWhere(self.filterFormats, {
Id: fmt.Id
});
if (filt) {
filt.enabled(true);
}
});
self.theatre(data);
}
});
};
self.changeFormat = function (format) {
console.log(format);
self.selectedFormat(format);
self.movies();
};
self.selectedDate.subscribe(function (newVal) {
self.getPerformances();
});
self.getPerformances();
// self.computedMovies = ko.computed(function () {
// var theseMovies = [];
// ko.utils.arrayForEach(self.movies, function (movie) {
// movie.isActive = ko.observable(false);
// movie.isSelected = ko.observable(false);
// theseMovies.push(movie);
// });
// return theseMovies;
// });
// self.toggleClass = function (sender) {
// sender.isActive(!sender.isActive());
// }
self.toggleHide = function () {
$('.icon.arrow').click(function () {
var active_el = $(this);
$('.movie-listing-header').each(function () {
if ($(this).get(0) === active_el.parent().get(0)) {
if ($(this).hasClass('active')) {
$(this).siblings('.showtimes').hide();
} else {
$(this).siblings('.showtimes').show();
}
$(this).toggleClass('active');
} else {
$(this).removeClass('active');
$(this).siblings('.showtimes').hide();
}
});
});
}
}
window.Regal.TheatreViewModel = TheatreViewModel;
my markup is populated, but the javascript does not work to hide and show the sibling.

Related

Uncaught TypeError: Cannot read property 'show' of undefined on the float box

I am getting the following error on all browsers while opening the float box and then it cannot be closed. You need to refresh the page. There was no problem before. It was working fine. Now, I've been getting this error ever since I adapted the new design to the site. How can fix this problem? Thank you.
Uncaught TypeError: Cannot read property 'show' of undefined
// disabling/enabling
jQuery.fn.extend({
disable: function() {
this.each(function()
{
this.disabled = true;
if ( this.tagName != 'INPUT' && this.tagName != 'TEXTAREA' && this.tagName != 'SELECT' )
{
this.jQuery_disabled_clone =
jQuery(this)
.addClass('disabled')
.clone()
.removeAttr('id')
.get(0);
jQuery(this)
.hide()
.bind('unload', function(){
jQuery(this).enable();
})
.after(this.jQuery_disabled_clone);
}
});
return this;
},
enable: function()
{
this.each(function()
{
this.disabled = false;
if ( this.jQuery_disabled_clone )
{
jQuery(this.jQuery_disabled_clone).remove();
this.jQuery_disabled_clone = null;
jQuery(this)
.unbind('unload', function(){
jQuery(this).enable();
})
.removeClass('disabled')
.show();
}
});
return this;
}
});
function SK_Exception(message, code)
{
this.toString = function() {
return message;
}
this.getCode = function() {
return code;
}
}
function SK_drawError(err_msg, delay) {
SK_drawMessage(err_msg, 'error', delay);
}
function SK_drawMessage(msg_text, type, delay)
{
if (navigator.appName == 'Microsoft Internet Explorer' && (msg_text == "Virtual gift has been sent" || msg_text == "Hediyeniz başarıyla gönderildi.." || msg_text == "Virtual gift has not been sent" || msg_text == "Hediyeniz gönderilemedi.."))
alert(msg_text);
type = type || 'message';
delay = delay || (1000*10);
if (SK_drawMessage.in_process) {
if (msg_text) {
SK_drawMessage.queue.unshift([msg_text, type, delay]);
}
return;
}
if (!msg_text) {
var item = SK_drawMessage.queue.shift();
if (!item) {
return;
}
msg_text = item[0];
type = item[1];
delay = item[2];
}
SK_drawMessage.in_process = true;
// getting draw position
var $last = jQuery('.macos_msg_node:last');
var top_pos = (!$last.length) ? 0 : $last.position().top + $last.outerHeight() + 2;
var $msg_block =
// creating message block
jQuery('<div class="macos_msg_node macos_'+type+'" style="display: none"></div>')
.appendTo('body')
.html(msg_text)
.prepend('<a class="close_btn" href="#"></a>')
.css('top', top_pos)
.fadeTo(50, 0.1, function() {
jQuery(this).css('display', '');
SK_drawMessage.in_process = false;
SK_drawMessage();
jQuery(this).fadeTo(300, 1, function() {
if (delay > 0) {
window.setTimeout(function() {
try {
$msg_block.fadeOut(2500, function() {
jQuery(this).remove();
});
} catch (e) {alert(e);}
}, delay);
}
});
});
$msg_block.children('.close_btn')
.click(function() {
jQuery(this).parent().fadeOut(100, function() {
jQuery(this).remove();
});
return false;
}
);
}
SK_drawMessage.in_process = false;
SK_drawMessage.queue = [];
/**
* Float box constructor.
*
* #param string|jQuery $title
* #param string|jQuery $contents
* #param jQuery $controls
* #param object position {top, left} = center
* #param integer width = auto
* #param integer height = auto
*/
function SK_FloatBox(options)
{
var fb_class;
if (typeof document.body.style.maxHeight === 'undefined') { //if IE 6
jQuery('body').css({height: '100%', width: '100%'});
jQuery('html').css('overflow', 'hidden');
if (document.getElementById('floatbox_HideSelect') === null) { //iframe to hide select elements in ie6
jQuery('body').append('<iframe id="floatbox_HideSelect"></iframe><div id="floatbox_overlay"></div>');
fb_class = SK_FloatBox.detectMacXFF() ? 'floatbox_overlayMacFFBGHack' : 'floatbox_overlayBG';
jQuery('#floatbox_overlay').addClass(fb_class);
}
}
else { //all others
if (document.getElementById('floatbox_overlay') === null) {
jQuery('body').append('<div id="floatbox_overlay"></div>');
fb_class = SK_FloatBox.detectMacXFF() ? 'floatbox_overlayMacFFBGHack' : 'floatbox_overlayBG';
jQuery('#floatbox_overlay').addClass(fb_class);
}
}
jQuery('body').css('overflow', 'hidden');
this.$container = jQuery('.floatbox_container', '#sk-floatbox-block-prototype').clone().appendTo('body');
this.$header = this.$container.find('.block_cap_title');
if (typeof options.$title == 'string') {
options.$title = jQuery('<span>'+options.$title+'</span>');
}
else {
this.$title_parent = options.$title.parent();
}
this.$header.append(options.$title);
this.$body = this.$container.find('.block_body_c');
if (typeof options.$contents == 'string') {
options.$contents = jQuery('<span>'+options.$contents+'</span>');
}
else {
this.$contents_parent = options.$contents.parent();
}
this.$body.append(options.$contents);
this.$bottom = this.$container.find('.block_bottom_c');
if (options.$controls) {
if (typeof options.$controls == 'string') {
options.$controls = jQuery('<span>'+options.$controls+'</span>');
}
else {
this.$controls_parent = options.$controls.parent();
}
this.$bottom.append(options.$controls);
}
if (options.width)
this.$container.css("width", options.width);
if (options.height)
this.$container.css("height", options.height);
var fl_box = this;
jQuery('.close_btn', this.$container.find('.floatbox_header'))
.one('click', function() {
fl_box.close();
return false;
});
this.esc_listener =
function(event) {
if (event.keyCode == 27) {
fl_box.close();
return false;
}
return true;
}
jQuery(document).bind('keydown', this.esc_listener);
this.$container
.fadeTo(1, 0.1, function()
{
var $this = jQuery(this);
$this.css('display', 'block');
if (options.position) {
$this.css(options.position);
}
else {
var position = {
top:((jQuery(window).height()/2) - ($this.height()/2))/*.ceil()*/,
left:((jQuery(window).width()/2) - ($this.width()/2))/*.ceil()*/
};
$this.css(position);
}
// trigger on show event
fl_box.trigger('show');
$this.fadeTo(100, 1);
});
this.events = {close: [], show: []};
}
SK_FloatBox.detectMacXFF = function()
{
var userAgent = navigator.userAgent.toLowerCase();
return (userAgent.indexOf('mac') != -1 && userAgent.indexOf('firefox') != -1);
}
SK_FloatBox.prototype = {
close: function()
{
if (this.trigger('close') === false) {
return false;
}
jQuery(document).unbind('keydown', this.esc_listener);
if (this.$title_parent && this.$title_parent.length) {
this.$title_parent.append(
this.$header.children()
);
}
if (this.$contents_parent && this.$contents_parent.length) {
this.$contents_parent.append(this.$body.children());
}
if (this.$controls_parent && this.$controls_parent.length) {
this.$controls_parent.append(this.$bottom.children());
}
this.$container.remove();
if (jQuery('.floatbox_container:not("#sk-floatbox-block-prototype .floatbox_container")').length === 0) {
jQuery('body').css('overflow', '');
jQuery('#floatbox_overlay, #floatbox_HideSelect').remove();
}
return true;
},
bind: function(type, func)
{
if (this.events[type] == undefined) {
throw 'form error: unknown event type "'+type+'"';
}
this.events[type].push(func);
},
trigger: function(type, params)
{
if (this.events[type] == undefined) {
throw 'form error: unknown event type "'+type+'"';
}
params = params || [];
for (var i = 0, func; func = this.events[type][i]; i++) {
if (func.apply(this, params) === false) {
return false;
}
}
return true;
}
}
function SK_alert($title, $contents, callback)
{
if (!callback &&
typeof $contents == 'function' &&
$contents.constructor != Array) {
callback = $contents;
}
if (!$contents || $contents == callback) {
$contents = $title;
$title = SK_Language.text('%interface.alert_title');
}
var $ok_btn =
jQuery('<input type="button" />')
.val(SK_Language.text('%interface.ok'));
var fl_box = new SK_FloatBox({
$title: $title,
$contents: $contents,
$controls: $ok_btn
});
$ok_btn.one('click', function() {
fl_box.close();
if (callback) {
callback.apply(fl_box);
}
});
return fl_box;
}
function SK_confirm($title, $contents, callback)
{
if (!callback &&
typeof $contents == 'function' &&
$contents.constructor != Array) {
callback = $contents;
}
if (!$contents || $contents == callback) {
$contents = $title;
$title = SK_Language.text('%interface.confirmation_title');
}
var $ok_btn =
jQuery('<input type="button" />')
.val(SK_Language.text('%interface.ok'));
var $cancel_btn =
jQuery('<input type="button" />')
.val(SK_Language.text('%interface.cancel'));
var fl_box = new SK_FloatBox({
$title: $title,
$contents: $contents,
$controls: jQuery($ok_btn)
.add('<span> </span>')
.add($cancel_btn)
});
$ok_btn.one('click', function() {
fl_box.close();
if (callback) {
callback.apply(fl_box);
}
});
$cancel_btn.one('click', function() {
fl_box.close();
});
return fl_box;
}
function SK_BlockHandler(block_node)
{
this.$block = jQuery(block_node);
this.$block_cap =
jQuery('.block_cap:eq(0)', this.$block);
this.$title =
jQuery('.block_cap_title:eq(0)', this.$block_cap);
this.$body =
jQuery('.block_body:eq(0)', this.$block);
this.$expand_btn =
jQuery('.block_expand:eq(0), .block_collapse:eq(0)', this.$block_cap);
this.events = {
click: [],
expand: [],
collapse: []
}
var handler = this;
this.$block_cap
.click(function() {
if (handler.$expand_btn.hasClass('block_expand')) {
handler.expand();
}
else if (handler.$expand_btn.hasClass('block_collapse')) {
handler.collapse();
}
return false;
});
}
SK_BlockHandler.prototype = {
expand: function(trigger_events)
{
if (trigger_events === undefined) {
trigger_events = true;
}
if (!trigger_events || (
this.trigger('expand') !== false
&& this.trigger('click') !== false)
) {
this.$expand_btn.attr('class', 'block_collapse');
this.$body.slideDown('fast');
}
return this;
},
collapse: function(trigger_events)
{
if (trigger_events === undefined) {
trigger_events = true;
}
if (!trigger_events || (
this.trigger('collapse') !== false
&& this.trigger('click') !== false)
) {
this.$expand_btn.attr('class', 'block_expand');
this.$body.slideUp('fast');
}
return this;
},
show: function(speed, callback) {
this.$block.show(speed, callback);
},
hide: function(speed, callback) {
this.$block.hide(speed, callback);
},
bind: function(type, arg1, arg2)
{
if (this.events[type] == undefined) {
throw 'block error: unknown event type "'+type+'"';
}
if (!arg2) {
this.events[type].push([arg1]);
}
else {
this.events[type].push([arg1, arg2]);
}
},
trigger: function(type)
{
if (this.events[type] == undefined) {
throw 'block error: unknown event type "'+type+'"';
}
for (var i = 0, item; item = this.events[type][i]; i++)
{
if (item.length == 1) {
if (item[0].apply(this) === false) {
return false;
}
}
else if (item[1].call(this, item[0]) === false) {
return false;
}
}
return true;
},
clone: function(clone_e)
{
var $clone = this.$block.clone();
var node = $clone.get(0);
node.sk_block_handler = new SK_BlockHandler(node);
if (clone_e) {
node.sk_block_handler.events = this.events;
}
return node.sk_block_handler;
},
append: function(content) {
return this.$body.append(content);
return this;
},
appendTo: function(content) {
this.$block.appendTo(content);
return this;
},
empty: function() {
this.$body.empty();
return this;
},
children: function(expr) {
return this.$body.children(expr).not('.block_body_corner');
},
find: function(expr) {
return this.$body.find(expr).not('.block_body_corner');
},
removeAttr: function(name) {
this.$block.removeAttr(name);
return this;
},
addClass: function(cls) {
this.$block.addClass(cls);
return this;
},
removeClass: function(cls) {
this.$block.removeClass(cls);
return this;
}
}
jQuery(function() {
jQuery('.block_expand, .block_collapse')
.each(function() {
var block_node = this.parentNode.parentNode.parentNode.parentNode;
if (jQuery(block_node).hasClass('block')) {
block_node.sk_block_handler = new SK_BlockHandler(block_node);
}
});
});
SK_Language = {
data: {},
text: function(lang_addr, var_list)
{
if ( SK_Language.data[lang_addr] === undefined ) {
throw new SK_Exception('language section ['+lang_addr+'] not found');
}
var text = SK_Language.data[lang_addr];
if (var_list) {
for ( key in var_list ) {
text = text.replace('{$'+key+'}', var_list[key]);
}
}
return text;
}
}
function nl2br(str) {
return (str + '').replace(/([^>]?)\n/g, '$1<br />\n');
}
function SK_SignIn() {
return window.sk_component_sign_in.showBox();
}
function SK_openIM(opponent_id, is_esd)
{
if (is_esd)
is_esd_session = '&is_esd_session='+is_esd;
else
is_esd_session = '';
return window.open(
URL_MEMBER+'im.php?opponent_id='+opponent_id+is_esd_session,
'im_with_'+opponent_id,
'width='+SK_openIM.width+','+
'height='+SK_openIM.height+','+
'resizable=yes, location=no, scrollbars=no, status=no'
);
}
SK_openIM.width = 445;
SK_openIM.height = 460;
function SK_profileNote( event_id, opponent_id)
{
return window.open(
URL_MEMBER+'profile_note.php?event_id='+event_id+'&opponent_id='+opponent_id,
'note_'+opponent_id,
'width='+SK_profileNote.width+','+
'height='+SK_profileNote.height+','+
'resizable=yes, location=no, scrollbars=no, status=no'
);
}
SK_profileNote.width = 325;
SK_profileNote.height = 425;
SK_EventManager = {
events: {},
bind: function(event, callback)
{
if ( typeof this.events[event] == 'undefined' || this.events[event] === null)
{
this.events[event] = [];
}
this.events[event].push(callback);
},
trigger: function(event, eventObject)
{
if (typeof this.events[event] != 'undefined' && this.events[event] !== null)
{
for (var i = 0; i < this.events[event].length; i++)
{
if (typeof this.events[event][i] == 'function')
{
if (this.events[event][i](eventObject) === false)
{
return;
}
}
}
}
}
};
SK_SetFieldInvitation = function(id, label)
{
var $node = $('#' + id);
$node.addClass('input_invitation').val(label);
$node.focus(function() {
var v = $node.val();
$node.removeClass('input_invitation');
if ( v == label )
{
$node.val('');
}
}).blur(function() {
var v = $node.val();
if ( !v )
{
$node.addClass('input_invitation').val(label);
}
});
$($node.get(0).form).submit(function(){
if ( $node.val() != label )
{
$node.removeClass('input_invitation');
}
});
}
<div class="floatbox_container" style="overflow: visible; width: 320px; opacity: 0.1; display: block; top: 274px; left: 736px;">
<div class="block_cap floatbox_header"><div class="block_cap_r"><div class="block_cap_c clearfix"><h3 class="block_cap_title"><b>Şifremi unuttum!</b></h3><a class="close_btn" href="#"></a></div></div></div> <div class="floatbox_body">
<div class="fblock_body block_body">
<div class="fblock_body_r block_body_r">
<div class="fblock_body_c block_body_c">
<div class="block_info">Şifremi yenile</div><form id="form_3" method="post" onsubmit="return false;">
<label>E-posta</label>: <input id="form_3-email" name="email" type="text" maxlength="255">
<div id="form_3-email-container"></div>
<div class="controls center float_left">
<input id="form_3-send-button" type="submit" value="Gönder"> </div>
<div class="clr"></div>
</form></div>
</div>
</div>
</div>
<div class="floatbox_bottom">
<div class="block_bottom">
<div class="block_bottom_r">
<div class="block_bottom_c">
</div>
</div>
</div>
</div>
<div class="fblock_bottom">
<div class="fblock_bottom_r">
<div class="fblock_bottom_c"></div>
</div>
</div>
</div>

Delete specific item from local storage

I have a note taking application that im working on . Its made to look like Google Keep
It saves each note in local storage .
I would like to add a delete option to each of the notes (similar to Keep) , but don't know know to do it.
The full code is on my Github page https://github.com/oxhey/keep
HTML :
<!doctype html>
<html>
<head>
<title>Notes</title>
<link href="styles/normalize.css" rel="stylesheet" />
<link href="styles/main.css" rel="stylesheet" />
<link rel="stylesheet" type="text/css" href="window.css">
</head>
<script>
var nw = require('nw.gui');
var win = nw.Window.get();
win.isMaximized = false;
</script>
<body id="gui">
<header class="app-header">
<ul style="margin-top:0.3px">
<li><a href='#' title='Close' id='windowControlClose'></a></li>
<li><a href='#' title='Maximize' id='windowControlMaximize'></a></li>
<li><a href='#' title='Minimize' id='windowControlMinimize'></a></li>
</ul>
<h2 style="margin-top: 10px;margin-left: 20px;color: #fff;">Notes</h2>
</header>
<section class="main-section">
<article class="note add-note">
<h1 class="note-title"></h1>
<p class="note-content">Add a note</p>
</article>
</section>
<script src="js/jquery.js"></script>
<script src="js/main.js"></script>
<script>
// Min
document.getElementById('windowControlMinimize').onclick = function()
{
win.minimize();
};
// Close
document.getElementById('windowControlClose').onclick = function()
{
win.close();
gui.App.closeAllWindows();
};
// Max
document.getElementById('windowControlMaximize').onclick = function()
{
if (win.isMaximized)
win.unmaximize();
else
win.maximize();
};
win.on('maximize', function(){
win.isMaximized = true;
});
win.on('unmaximize', function(){
win.isMaximized = false;
});
</script>
</body>
</html>
Javascript : Main.js
var Strings = {
'en-us': {
DEFAULT_TITLE: "Title",
ADD_NOTE: "Add a note",
SEARCH_PLACEHOLDER: "Search Jin's Keep"
}
};
var Lang = Strings['en-us'];
var Keys = {
ENTER: 10
}
var notes;
function Note(title, content, id) {
Note.numInstances = (Note.numInstances || 0) + 1;
this.id = id ? id : Note.numInstances
this.title = title;
this.content = content;
}
Note.prototype.render = function(index) {
var elem = $('<article class="note" data-index="' + index + '"><h1 class="note-title">' + this.title + '</h1><p class="note-content">' + this.content + '</p></article>');
$(".add-note").after(elem);
}
Note.prototype.toJSON = function() {
return {
id: this.id,
title: this.title,
content: this.content
};
}
function createNote() {
var elem = $(".add-note");
var title = elem.find(".note-title");
var content = elem.find(".note-content");
elem.removeClass("active");
title.hide();
if(title.text() != Lang.DEFAULT_TITLE || content.text() != Lang.ADD_NOTE) {
var id = notes ? notes.length+1 : 1;
var note = new Note(title.text(), content.text(), id);
notes.push(note);
note.render(notes.length-1);
title.text(Lang.DEFAULT_TITLE);
content.text(Lang.ADD_NOTE);
saveNotes();
}
}
function activateNote(note) {
var title = note.find(".note-title");
note.addClass("active");
title.show();
if(isEmpty(title.text())) {
title.text(Lang.DEFAULT_TITLE);
}
}
function saveCurrentNote() {
var noteElement = $(".note.active");
if(noteElement) {
console.log("will save this element: ", noteElement[0]);
var noteIndex = noteElement.attr("data-index");
var note = notes[noteIndex];
note.title = noteElement.find(".note-title").text();
note.content = noteElement.find(".note-content").text();
saveNotes();
deactivateCurrentNote(noteElement);
}
}
function deactivateCurrentNote(note) {
note.removeClass("active");
var title = note.find(".note-title");
if(isEmpty(title.text()) || title.text() == Lang.DEFAULT_TITLE) {
title.hide();
}
$(":focus").blur();
}
function isEmpty(string) {
return string.replace(/\s| /g, '').length == 0;
}
function addTabIndex() {
tabIndex = 3;
$(".note .note-content, .note .note-title").each(function() {
var el = $(this);
el.attr("tabindex", tabIndex++);
});
}
function loadNotes() {
var rawObjects = JSON.parse(localStorage.getItem("notes"));
if(rawObjects && rawObjects.length) {
rawObjects.forEach(function(obj, index) {
obj.__proto__ = Note.prototype;
obj.render(index);
});
return rawObjects;
} else {
console.warn("Couldn't load any note because local storage is empty.");
return [];
}
}
function saveNotes() {
localStorage.setItem("notes", JSON.stringify(notes))
}
$(document).ready(function() {
notes = loadNotes();
addTabIndex();
$(".note").each(function() {
var note = $(this);
var title = note.find(".note-title");
if(isEmpty(title.text()) || title.text() == Lang.DEFAULT_TITLE ) {
title.hide();
}
});
$(".main-section").on("click", ".note .note-content, .note .note-title", function(evt) {
var note = $(this).parent();
activateNote(note);
//console.log('2 - Setting content editable to true', evt);
var noteSection = $(this);
noteSection.prop("contentEditable", true);
});
$(".main-section").on("click", ".note .note-title", function(evt) {
//console.log("3 - Clearing TITLE's text");
var title = $(this);
if(title.text() == Lang.DEFAULT_TITLE) {
title.text("");
}
});
$(".main-section").on("click", ".note .note-content", function(evt) {
//console.log('4 - Clearing CONTENT text', evt);
var content = $(this);
if(content.text() == Lang.ADD_NOTE) {
content.text("");
content.focus();
}
});
$(".main-section").on("click", function(evt) {
if(evt.target == this) {
//console.log('5', evt);
var currentNote = $(".note.active");
if(currentNote.length) {
//console.log('5.a');
if(currentNote.hasClass("add-note")) {
console.log('5 - Creating a new note');
createNote();
} else {
console.log('5 - Saving current note');
saveCurrentNote();
}
if(currentNote.find(".note-title").text() == Lang.DEFAULT_TITLE) {
currentNote.find(".note-title").hide();
}
}
}
});
$(".main-section").on("keypress", ".note .note-content, .note .note-title", function(evt) {
var currentNote = $(".note.active");
console.log('6');
if(evt.which == Keys.ENTER && evt.ctrlKey) {
console.log('2');
if(currentNote.hasClass("add-note")) {
createNote();
} else {
saveCurrentNote();
}
}
});
});
Thanks
Something like this? Use a data attribute on a delete button and pass that as a parameter to a removeNote function.
HTML
<button class="delete" data-id="1">Delete note</button>
JS
$(document).on('click', '.delete', function () {
var id = $(this).data('id');
removeNote(id);
});
function removeNote(id) {
localStorage.removeItem(id);
}

Using knockout.js, is there anyway to control the div attributes contained within a foreach

Here is my asp.net
<div data-bind="foreach {data:movies}">
<div class="content-item full bottom-border">
<div class="content-item-container">
<div class="movie-listing-header">
<a class="icon arrow" data-bind="click: $parent.toggle"></a>
<div class="movie-details">
<div class="title"></div>
<div class="info">
<div class="rating">
</div>
<div class="time" data-bind=" text: movieruntime "></div>
</div>
</div>
<a class="icon right-arrow" href="#" data-bind="attr: { href: DetailsUrl }"></a>
</div>
<div class="showtimes">
<div data-bind="template: { name: 'movie-grouped-showtimes-template', data: $data }"></div>
</div>
</div>
</div>
</div>
What I would like to be able to do is simply, click on <a class"arrow icon"> and be able to toggle the following:
<div class="movie-listing-header"> -- addClass(.active);
<div class="showtimes"> -- style: block;
I can get the showtimes to work, but it adds the styling to each movie, and I want to control the toggle contained with the movie.
here is the .js
function TheatreViewModel(theatre) {
var self = this,
initialData = theatre || Regal.userPrimaryTheatre || {},
theatreServiceParams = {
tmsId: initialData.TmsId,
date: initialData.selectedDate || new Date()
};
self.TheatreName = initialData.TheatreName || '';
self.PhoneNumber = initialData.PhoneNumber || '';
self.selectedTheatreTms = initialData.TmsId;
self.theatre = ko.observable();
self.isLoading = ko.observable(false);
self.selectedDate = ko.observable(initialData.selectedDate || new Date());
self.filterFormats = [];
self.selectedFormat = ko.observable(Regal.allFormatsFilterItem);
self.filterFormats.push(Regal.allFormatsFilterItem);
if (Regal.movieFormats) {
var filtered = _.where(Regal.movieFormats, {
Filterable: true
});
_.forEach(filtered, function(f) {
f.enabled = ko.observable(false);
self.filterFormats.push(f);
});
}
self.addressText = ko.computed(function() {
var theat = ko.unwrap(self.theatre);
var addie;
if (!theat || theat && !theat.Address1) {
addie = initialData;
} else {
addie = theat;
}
return addie.Address1 + ', ' + addie.City + ' ' + addie.State + ' ' + addie.PostalCode;
});
self.mapEmbedUrl = ko.computed(function() {
var a = self.addressText();
return 'http://maps.google.com/maps?q=' + encodeURI(a);
});
self.movies = ko.computed(function() {
var thea = self.theatre(),
mov = ko.unwrap((thea || {}).Movies),
format = self.selectedFormat();
if (format && format !== Regal.allFormatsFilterItem) {
return _.filter(mov, function(m) {
return _.contains(_.pluck(m.formats(), 'Id'), format.Id);
});
}
return mov;
});
self.getPerformances = function() {
self.isLoading(true);
Regal.loadTheatre(self.selectedDate(), self.selectedTheatreTms,
function(data) {
self.isLoading(false);
if (data) {
var allFmts = _.uniq(_.flatten(_.map(ko.unwrap(data.Movies), function(mov) {
return mov.formats();
})));
_.forEach(allFmts, function(fmt) {
var filt = _.findWhere(self.filterFormats, {
Id: fmt.Id
});
if (filt) {
filt.enabled(true);
}
});
self.theatre(data);
}
});
};
self.changeFormat = function(format) {
console.log(format);
self.selectedFormat(format);
self.movies();
};
self.selectedDate.subscribe(function(newVal) {
self.getPerformances();
});
self.getPerformances();
self.toggle = function () {
$('.showtimes').show();
$('.movie-listing-header').addClass('.active');
}
}
window.Regal.TheatreViewModel = TheatreViewModel;
any help would be appreciated, I can't believe that this cannot be accomplished.
note: before I added knockout ... here is the jquery that was in place and working ...
$(document).ready(function () {
$('.icon.arrow').click(function () {
var active_el = $(this);
$('.movie-listing-header').each(function () {
if ($(this).get(0) === active_el.parent().get(0)) {
if ($(this).hasClass('active')) {
$(this).siblings('.showtimes').hide();
} else {
$(this).siblings('.showtimes').show();
}
$(this).toggleClass('active');
} else {
$(this).removeClass('active');
$(this).siblings('.showtimes').hide();
}
});
});
});
You could use a custom binding handler here but a more generic way of doing it would be as such -
Use the css and style bindings to toggle the classes -
<div data-bind="foreach: computedMovies">
<div class="movie-listing-header" data-bind="css: { 'active' : isActive() }, click: toggleClass">
<div class="showtimes" data-bind="style: { 'display': isSelected() ? 'block' : 'none' }">
</div>
</div>
</div>
And in your view model, create a computed to add some additional properties -
var computedMovies = ko.computed(function() {
var theseMovies = [];
ko.utils.arrayForEach(movies(), function (movie) {
movie.isActive = ko.observable(false);
movie.isSelected = ko.observable(false);
theseMovies.push(movie);
});
return movies;
});
function toggleClass() {
isActive(!isActive());
}
Edited with jsFiddle
http://jsfiddle.net/gNE77/

click event not completely working, using Knockout.js binding and viewmodel

hi this is my code snippet:
self.arrow = function () {
alert("button clicked");
var active_el = $(this);
$('.movie-listing-header').each(function () {
if ($(this).get(0) === active_el.parent().get(0)) {
if ($(this).hasClass('active')) {
$(this).siblings('.showtimes').hide();
} else {
$(this).siblings('.showtimes').show();
}
$(this).toggleClass('active');
} else {
$(this).removeClass('active');
$(this).siblings('.showtimes').hide();
}
});
}
it is part of my viewmodel, and the alert("button clicked") works, but the rest of the code does not ... Here is the button click code:
<a class="icon arrow" data-bind="click: $parent.arrow"></a>
my question is HOW do I get the code after the alert to function.
this is the entire js, containing the the View Model
function TheatreViewModel(theatre) {
var self = this,
initialData = theatre || Regal.userPrimaryTheatre || {},
theatreServiceParams = {
tmsId: initialData.TmsId,
date: initialData.selectedDate || new Date()
};
self.TheatreName = initialData.TheatreName || '';
self.PhoneNumber = initialData.PhoneNumber || '';
self.selectedTheatreTms = initialData.TmsId;
self.theatre = ko.observable();
self.isLoading = ko.observable(false);
self.selectedDate = ko.observable(initialData.selectedDate || new Date());
self.filterFormats = [];
self.selectedFormat = ko.observable(Regal.allFormatsFilterItem);
self.filterFormats.push(Regal.allFormatsFilterItem);
if (Regal.movieFormats) {
var filtered = _.where(Regal.movieFormats, {
Filterable: true
});
_.forEach(filtered, function(f) {
f.enabled = ko.observable(false);
self.filterFormats.push(f);
});
}
self.addressText = ko.computed(function() {
var theat = ko.unwrap(self.theatre);
var addie;
if (!theat || theat && !theat.Address1) {
addie = initialData;
} else {
addie = theat;
}
return addie.Address1 + ', ' + addie.City + ' ' + addie.State + ' ' + addie.PostalCode;
});
self.mapEmbedUrl = ko.computed(function() {
var a = self.addressText();
return 'http://maps.google.com/maps?q=' + encodeURI(a);
});
self.movies = ko.computed(function() {
var thea = self.theatre(),
mov = ko.unwrap((thea || {}).Movies),
format = self.selectedFormat();
if (format && format !== Regal.allFormatsFilterItem) {
return _.filter(mov, function(m) {
return _.contains(_.pluck(m.formats(), 'Id'), format.Id);
});
}
return mov;
});
self.getPerformances = function() {
self.isLoading(true);
Regal.loadTheatre(self.selectedDate(), self.selectedTheatreTms,
function(data) {
self.isLoading(false);
if (data) {
var allFmts = _.uniq(_.flatten(_.map(ko.unwrap(data.Movies), function(mov) {
return mov.formats();
})));
_.forEach(allFmts, function(fmt) {
var filt = _.findWhere(self.filterFormats, {
Id: fmt.Id
});
if (filt) {
filt.enabled(true);
}
});
self.theatre(data);
}
});
};
self.changeFormat = function(format) {
console.log(format);
self.selectedFormat(format);
self.movies();
};
self.selectedDate.subscribe(function(newVal) {
self.getPerformances();
});
self.getPerformances();
self.arrow = function () {
alert("button clicked");
var active_el = $(this);
$('.movie-listing-header').each(function () {
if ($(this).get(0) === active_el.parent().get(0)) {
if ($(this).hasClass('active')) {
$(this).siblings('.showtimes').hide();
} else {
$(this).siblings('.showtimes').show();
}
$(this).toggleClass('active');
} else {
$(this).removeClass('active');
$(this).siblings('.showtimes').hide();
}
});
}
}
I have a feeling that var active_el = $(this) is not what you're expecting. I'm not running the code but I believe that this will be self in this context. However, I'd like to recommend a more fundamental MVVM change. Rather than including all this jQuery code for updating the UI, I would recommend setting properties on your view model instead. Here's a simplified example:
HTML
<section data-bind="foreach: movies">
<article>
<div data-bind="if: displayShowtimes">
<!-- ... show times UI -->
</div>
</article>
</section>
JavaScript
self.arrow = function (movie) {
movie.isActive(!movie.isActive());
}
This will make your JavaScript much less brittle to changes in the HTML.

Attempting to use custom binding in knockout.js ... getting an error ... where do I look

this is my JS
function TheatreViewModel(theatre) {
var self = this,
initialData = theatre || Regal.userPrimaryTheatre || {},
theatreServiceParams = {
tmsId: initialData.TmsId,
date: initialData.selectedDate || new Date()
};
self.TheatreName = initialData.TheatreName || '';
self.PhoneNumber = initialData.PhoneNumber || '';
self.selectedTheatreTms = initialData.TmsId;
self.theatre = ko.observable();
self.isLoading = ko.observable(false);
self.selectedDate = ko.observable(initialData.selectedDate || new Date());
self.filterFormats = [];
self.selectedFormat = ko.observable(Regal.allFormatsFilterItem);
self.filterFormats.push(Regal.allFormatsFilterItem);
if (Regal.movieFormats) {
var filtered = _.where(Regal.movieFormats, {
Filterable: true
});
_.forEach(filtered, function (f) {
f.enabled = ko.observable(false);
self.filterFormats.push(f);
});
}
self.addressText = ko.computed(function () {
var theat = ko.unwrap(self.theatre);
var addie;
if (!theat || theat && !theat.Address1) {
addie = initialData;
} else {
addie = theat;
}
return addie.Address1 + ', ' + addie.City + ' ' + addie.State + ' ' + addie.PostalCode;
});
self.mapEmbedUrl = ko.computed(function () {
var a = self.addressText();
return 'http://maps.google.com/maps?q=' + encodeURI(a);
});
self.movies = ko.computed(function () {
var thea = self.theatre(),
mov = ko.unwrap((thea || {}).Movies),
format = self.selectedFormat();
if (format && format !== Regal.allFormatsFilterItem) {
return _.filter(mov, function (m) {
return _.contains(_.pluck(m.formats(), 'Id'), format.Id);
});
}
return mov;
});
self.getPerformances = function () {
self.isLoading(true);
Regal.loadTheatre(self.selectedDate(), self.selectedTheatreTms,
function (data) {
self.isLoading(false);
if (data) {
var allFmts = _.uniq(_.flatten(_.map(ko.unwrap(data.Movies), function (mov) {
return mov.formats();
})));
_.forEach(allFmts, function (fmt) {
var filt = _.findWhere(self.filterFormats, {
Id: fmt.Id
});
if (filt) {
filt.enabled(true);
}
});
self.theatre(data);
}
});
};
self.changeFormat = function (format) {
console.log(format);
self.selectedFormat(format);
self.movies();
};
self.selectedDate.subscribe(function (newVal) {
self.getPerformances();
});
self.getPerformances();
self.computedMovies = ko.computed(function () {
var theseMovies = [];
ko.utils.arrayForEach(self.movies, function (movie) {
movie.isActive = ko.observable(false);
movie.isSelected = ko.observable(false);
theseMovies.push(movie);
});
return theseMovies;
});
self.toggleClass = function (sender) {
sender.isActive(!sender.isActive());
// }
self.toggleHide = function () {
$('.icon.arrow').click(function () {
var active_el = $(this);
$('.movie-listing-header').each(function () {
if ($(this).get(0) === active_el.parent().get(0)) {
if ($(this).hasClass('active')) {
$(this).siblings('.showtimes').hide();
} else {
$(this).siblings('.showtimes').show();
}
$(this).toggleClass('active');
} else {
$(this).removeClass('active');
$(this).siblings('.showtimes').hide();
}
});
});
}
}
window.Regal.TheatreViewModel = TheatreViewModel;
the self.computedMovies should return an array that will add some more properties to bind in the markup to help control the css and the style ... I think this will work, but I am getting a hard error in the knockout.debug telling me that my array "self.movies" used in the self.computedMovies is NULL, notice the function is created earlier in the theatreViewModel ... but here is the markup, and the this is the error :
<div data-bind="foreach : {data:movies}">
<div class="content-item full bottom-border">
<div class="content-item-container">
<div data-bind="foreach : computedMovies">
<div class="movie-listing-header" data-bind="css: { 'active' : isActive()}, click: $parent.toggleClass ">
<a class="icon arrow"></a>
<div class="movie-details">
<div class="title"></div>
<div class="info">
<div class="rating">
</div>
<div class="time" data-bind=" text: movieruntime "></div>
</div>
</div>
<a class="icon right-arrow" href="#" data-bind="attr: { href: DetailsUrl }"></a>
</div>
<div class="showtimes" data-bind="style: { 'display': isSelected() ? 'block' : 'none' }">
<div data-bind="template: { name: 'movie-grouped-showtimes-template', data: $data }"></div>
</div>
</div>
</div>
</div>
</div>
"Uncaught exception error the property "length" is not defined ...
any ideas on how to track this down, I am starting to take other options, but I would like to understand why this is not working, considering the self.movies is used to populate the markup and that IS working.
javascript I am trying to run, after the page is loaded:
$('.icon.arrow').click(function () {
var active_el = $(this);
$('.movie-listing-header').each(function () {
if ($(this).get(0) === active_el.parent().get(0)) {
if ($(this).hasClass('active')) {
$(this).siblings('.showtimes').hide();
} else {
$(this).siblings('.showtimes').show();
}
$(this).toggleClass('active');
} else {
$(this).removeClass('active');
$(this).siblings('.showtimes').hide();
}
});
});
The question you're currently asking ("How to track this down?") doesn't have much to do with the actual problem IMO. You basically have two paths:
Debug the error as is, using a debugger (e.g. Firebug) with breakpoints, "console.log debugging", etc.
Create a reproducible scenario as small as possible.
The first is the more direct approach and one to try for a short while first. If it fails I'd resort to the second approach. If you have no idea where to start I'd say that binary search debugging is a mix of the two.
Once you've found the root cause and/or have a small repro, you probably also have the solution. If not you can post a follow-up SO question with the code to repro the issue (optionally extended with a fiddle), with a repro it's very likely someone can help you.

Categories