@initKO = -> ko.bindingHandlers.fadeVisible = init : (element, valueAccessor) -> shouldDisplay = ko.utils.unwrapObservable(valueAccessor()) if shouldDisplay then $(element).show() else $(element).hide() update : (element, value) -> shouldDisplay = value() if shouldDisplay then $(element).fadeIn('slow') else $(element).hide() ko.bindingHandlers.slideVisible = init : (element, valueAccessor) -> shouldDisplay = ko.utils.unwrapObservable(valueAccessor()) if shouldDisplay then $(element).show() else $(element).hide() update : (element, valueAccessor) -> shouldDisplay = ko.utils.unwrapObservable(valueAccessor()) if shouldDisplay then $(element).slideDown('slow') else $(element).slideUp() # buttonStatus - [is_loading, ready_str, loading_str, icon_classes] ko.bindingHandlers.buttonStatus = update : (element, valueAccessor) -> opts = ko.utils.unwrapObservable(valueAccessor()) if opts[0] $(element).html(opts[2]) $(element).attr('disabled', 'true') else if opts[3]? txt = " #{opts[1]}" else txt = opts[1] $(element).html(txt) $(element).removeAttr('disabled') # labelStatus - [list, none_str, loading_str] ko.bindingHandlers.listStatus = init : (element, valueAccessor) -> opts = ko.utils.unwrapObservable(valueAccessor()) if opts[0].is_loading() $(element).html(opts[2]) $(element).show() else if opts[0].hasItems() $(element).hide() else $(element).show() $(element).html(opts[1]) update : (element, valueAccessor) -> opts = ko.utils.unwrapObservable(valueAccessor()) opts[0].is_loading.subscribe -> if opts[0].is_loading() $(element).html(opts[2]) $(element).show() else if opts[0].hasItems() $(element).hide() else $(element).show() $(element).html(opts[1]) ko.bindingHandlers.viewOptions = update : (element, valueAccessor) -> $(element).empty() opts = ko.utils.unwrapObservable(valueAccessor()) for view in opts[0] $(element).append("") if opts[3]? $(element).prepend("") ko.bindingHandlers.handleEnter = init : (element, valueAccessor, bindingsAccessor, viewModel) -> $(element).keypress (ev)-> if (ev.keyCode == 13 && !ev.shiftKey) action = valueAccessor() val = bindingsAccessor().value val($(element).val()) action.call(viewModel) return false ko.bindingHandlers.touchstart = init : (element, valueAccessor, bindingsAccessor, viewModel) -> element.addEventListener('touchstart', valueAccessor().bind(viewModel)) ko.bindingHandlers.validate = update : (element, valueAccessor) -> opts = valueAccessor() if opts.test() $(element).removeClass(opts.err_css) $(element).addClass(opts.ok_css) else $(element).removeClass(opts.ok_css) $(element).addClass(opts.err_css) opts.on_err() if opts.on_err? ko.bindingHandlers.cropImage = update : (element, valueAccessor) -> opts = valueAccessor() if opts[0]? $(element).css background : 'url(' + ko.utils.unwrapObservable(opts[0]) + ')', backgroundSize: 'cover', 'background-position': 'center', backgroundColor: '#FFF', width: opts[1], height: opts[2], display: 'inline-block' ko.bindingHandlers.checkedInt = init: (element, valueAccessor, allBindingsAccessor) -> observable = valueAccessor() interceptor = ko.computed read: -> return observable().toString() write: (newValue) -> observable(+newValue) owner: this ko.applyBindingsToNode(element, { checked: interceptor }) ko.bindingHandlers.untabbable = update : (element, valueAccessor, bindingsAccessor, viewModel) -> if (valueAccessor()) $(element).find('iframe, input, textarea, a, iframe').attr('tabIndex', -1) else $(element).find('input, textarea, a, iframe').removeAttr('tabIndex') ko.bindingHandlers.carousel = init : (element, valueAccessor, bindingsAccessor, viewModel) -> setTimeout -> idx = viewModel.getViewBoxIndex(viewModel.task()) new_el = $(element).find('.slide-item-' + idx).first() #new_el.addClass('active') , 0 update : (element, valueAccessor, bindingsAccessor, viewModel) -> opts = viewModel.transition.opts if viewModel.task() != null setTimeout -> idx = viewModel.getViewBoxIndex(viewModel.task()) console.log(viewModel.name + ': updating slider to ' + idx) old_idx = opts.slide_index() new_el = $(element).find('.slide-item-' + idx).first() old_el = $(element).find('.slide-item-' + old_idx).first() if idx > old_idx new_el.addClass('next') new_el[0].offsetWidth if new_el[0]? old_el.addClass('left') new_el.addClass('left') else new_el.addClass('prev') new_el[0].offsetWidth if new_el[0]? old_el.addClass('right') new_el.addClass('right') setTimeout -> new_el.removeClass('next left prev right') old_el.removeClass('next left prev right') old_el.removeClass('active') new_el.addClass('active') , 600 opts.slide_index(idx) , 0 ko.bindingHandlers.bindelem = init : (element, valueAccessor, bindingsAccessor, viewModel) -> viewModel.element = element ko.bindingHandlers.tinymce = init : (element, valueAccessor, bindingsAccessor, viewModel) -> options = { width : $(element).width(), height : $(element).height(), theme : 'advanced', theme_advanced_toolbar_location : 'top', theme_advanced_buttons1 : 'bold, italic, underline, separator, undo, redo, separator, bullist, numlist, blockquote, separator, justifyleft, justifycenter, justifyright, separator, image, link, unlink, separator, code', theme_advanced_buttons2 : '', theme_advanced_buttons3 : '' } val = valueAccessor() options.setup = (ed) -> ed.onInit.add (ed, l) -> tinyMCE.dom.Event.add ed.getWin(), "blur", -> console.log('leaving...') val(ed.getContent()) # handle destroying an editor (based on what jQuery plugin does) ko.utils.domNodeDisposal.addDisposeCallback element, -> ed = tinyMCE.get(element.id) if (ed) ed.remove() console.log('removing tinymce') setTimeout -> $(element).tinymce(options) if ($(element).attr('name') != 'undefined') ko.editors[$(element).attr('name')] = element.id , 100 console.log('init tinymce') update : (element, valueAccessor) -> $(element).html(ko.utils.unwrapObservable(valueAccessor())) ko.bindingHandlers.jsfileupload = init : (element, valueAccessor, bindingsAccessor, viewModel) -> model = valueAccessor() $(element).fileupload(model.input.options) $(element).change (evt)-> model.input.files(evt.target.files) model.fileupload = $(element).fileupload.bind($(element)) model.selectFile = -> $(element).click() ko.bindingHandlers.fileupload = init : (element, valueAccessor, bindingsAccessor, viewModel) -> model = valueAccessor() $(element).change (evt)-> model.input.files(evt.target.files) model.selectFile = -> $(element).click() ko.bindingHandlers.jqtabs = init : (element, valueAccessor, bindingsAccessor, viewModel) -> $(element).addClass('ui-tabs ui-widget ui-widget-content ui-corner-all') $(element).children('ul').first().addClass('ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all') $(element).children('ul').first().children('li').addClass('ui-state-default ui-corner-top') $(element).children('div').addClass('ui-tabs-panel ui-widget-content ui-corner-bottom') $(element).children('ul').first().find('li a').each (idx, el)-> tab_id = $(el).parent()[0].id $(el).click -> valueAccessor()(tab_id) update : (element, valueAccessor, bindingsAccessor, viewModel) -> sel_tab = ko.utils.unwrapObservable(valueAccessor()) $(element).children('ul').first().children('li').removeClass('ui-tabs-selected ui-state-active') $(element).children('ul').first().children("li##{sel_tab}").addClass('ui-tabs-selected ui-state-active') $(element).children('div').addClass('ui-tabs-hide') $(element).children("div##{sel_tab}").removeClass('ui-tabs-hide') ko.bindingHandlers.tabs = init : (element, valueAccessor, bindingsAccessor, viewModel) -> $(element).children('li').each (idx, el)-> tab_id = $(el)[0].id $(el).click -> valueAccessor()(tab_id) update : (element, valueAccessor, bindingsAccessor, viewModel) -> sel_tab = ko.utils.unwrapObservable(valueAccessor()) $(element).children('li').removeClass('active') $(element).children("li##{sel_tab}").addClass('active') ko.bindingHandlers.tab_views = update : (element, valueAccessor, bindingsAccessor, viewModel) -> sel_tab = ko.utils.unwrapObservable(valueAccessor()) $(element).children('div').addClass('hidden').removeClass('active') $(element).children("div##{sel_tab}").addClass('active').removeClass('hidden') ko.bindingHandlers.calendar = init : (element, valueAccessor, bindingsAccessor, viewModel) -> console.log('calendar init') $(element).fullCalendar('destroy') opts = $.extend({}, ko.utils.unwrapObservable(valueAccessor())) $(element).fullCalendar(opts) viewModel.calendar = $(element).fullCalendar.bind($(element)) ko.bindingHandlers.center = init : (element, valueAccessor, bindingsAccessor, viewModel) -> viewModel.task.subscribe -> setTimeout -> $(element).center() , 1 ko.bindingHandlers.progressbar = update: (element, valueAccessor) -> $(element).progressbar({value : ko.utils.unwrapObservable(valueAccessor())}) ko.bindingHandlers.placeholder = init: (element, valueAccessor) -> fn = -> if ($(element).val().length > 0) $(element).siblings('label').hide() else $(element).siblings('label').show() $(element).live('blur change keyup', fn) update: (element, valueAccessor) -> if ($(element).val().length > 0) $(element).siblings('label').hide() else $(element).siblings('label').show() ko.bindingHandlers.tip = init : (element, valueAccessor) -> opts = valueAccessor() $(element).tooltip placement: opts.placement || 'bottom' delay: opts.delay || 0 title: -> ko.utils.unwrapObservable(opts.content) ko.absorbModel = (data, self) -> for prop, val of data continue if typeof(val) == "function" if !self[prop]? self[prop] = ko.observable(val) else if (typeof(self[prop].handleData) == "function") self[prop].handleData(val) else self[prop](val) self.fields.pushOnce(prop) self.model_state(ko.modelStates.READY) ko.addFields = (fields, val, self) -> for prop in fields ko.addField prop, val, self ko.addField = (field, val, valid_fn, self) -> if !self? self = valid_fn valid_fn = null if (typeof(self[field]) != "function") if (val instanceof Array) self[field] = ko.observableArray() else self[field] = ko.observable(val) self["#{field}_valid"] = ko.computed( (-> (valid_fn.bind(self))(self[field]())), self) if valid_fn? else self[field](val) if (typeof(field) == "string") self.fields.pushOnce(field) ko.validate_for = (field, fn, msg, self) -> self.validations = {} unless self.validations? self.validations[field] = [] unless self.validations[field]? self.validations[field].push {test : fn.bind(self), msg : msg} self[field].is_valid = ko.computed -> valid = true for val_obj in self.validations[field] valid &&= val_obj.test(self[field]()) valid , self unless self[field].is_valid? ko.validate_fields = (fields, fn, self) -> msgs = [] for field in fields for val_obj in self.validations[field] if !val_obj.test(self[field]()) msgs.push val_obj.msg fn(msgs) ko.addSubModel = (field, model, self) -> if self[field]? self[field].reset() else self[field] = new model({}, self) self.fields.pushOnce(field) if typeof(field) == "string" ko.intercepter = (observable, write_fn, self) -> underlying_observable = observable return ko.dependentObservable read: underlying_observable, write: (val) -> if (val != underlying_observable()) write_fn.call(self, underlying_observable, underlying_observable(), val) ko.dirtyFlag = (root, isInitiallyDirty) -> result = -> _initialState = ko.observable(ko.toJSON(root)) _isInitiallyDirty = ko.observable(isInitiallyDirty) result.isDirty = ko.dependentObservable -> return _isInitiallyDirty() || (_initialState() != ko.toJSON(root)) result.reset = -> _initialState(ko.toJSON(root)) _isInitiallyDirty(false) return result ko.copyObject = (obj, fields) -> ret = {} for prop in fields ret[prop] = obj[prop] return ret ko.addTemplate = (templateName, templateMarkup) -> $('head').append("