big refactoring, and more
New routes, new juice flow, the tags on posts
This commit is contained in:
parent
d04a68db01
commit
1805cb3e17
46 changed files with 1339 additions and 515 deletions
189
web/Scripts/knockout-jqAutocomplete.js
Normal file
189
web/Scripts/knockout-jqAutocomplete.js
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
// knockout-jqAutocomplete 0.4.3 | (c) 2015 Ryan Niemeyer | http://www.opensource.org/licenses/mit-license
|
||||
;(function(factory) {
|
||||
if (typeof define === "function" && define.amd) {
|
||||
// AMD anonymous module
|
||||
define(["knockout", "jquery", "jquery-ui/autocomplete"], factory);
|
||||
} else {
|
||||
// No module loader - put directly in global namespace
|
||||
factory(window.ko, jQuery);
|
||||
}
|
||||
})(function(ko, $) {
|
||||
var JqAuto = function() {
|
||||
var self = this,
|
||||
unwrap = ko.utils.unwrapObservable; //support older KO versions that did not have ko.unwrap
|
||||
|
||||
//binding's init function
|
||||
this.init = function(element, valueAccessor, allBindings, data, context) {
|
||||
var existingSelect, existingChange,
|
||||
options = unwrap(valueAccessor()),
|
||||
config = {},
|
||||
filter = typeof options.filter === "function" ? options.filter : self.defaultFilter;
|
||||
|
||||
//extend with global options
|
||||
ko.utils.extend(config, self.options);
|
||||
//override with options passed in binding
|
||||
ko.utils.extend(config, options.options);
|
||||
|
||||
//get source from a function (can be remote call)
|
||||
if (typeof options.source === "function" && !ko.isObservable(options.source)) {
|
||||
config.source = function(request, response) {
|
||||
//provide a wrapper to the normal response callback
|
||||
var callback = function(data) {
|
||||
self.processOptions(valueAccessor, null, data, request, response);
|
||||
};
|
||||
|
||||
//call the provided function for retrieving data
|
||||
options.source.call(context.$data, request.term, callback);
|
||||
};
|
||||
}
|
||||
else {
|
||||
//process local data
|
||||
config.source = self.processOptions.bind(self, valueAccessor, filter, options.source);
|
||||
}
|
||||
|
||||
//save any passed in select/change calls
|
||||
existingSelect = typeof config.select === "function" && config.select;
|
||||
existingChange = typeof config.change === "function" && config.change;
|
||||
|
||||
//handle updating the actual value
|
||||
config.select = function(event, ui) {
|
||||
if (ui.item && ui.item.actual) {
|
||||
options.value(ui.item.actual);
|
||||
|
||||
if (ko.isWriteableObservable(options.dataValue)) {
|
||||
options.dataValue(ui.item.data);
|
||||
}
|
||||
}
|
||||
|
||||
if (existingSelect) {
|
||||
existingSelect.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
//user made a change without selecting a value from the list
|
||||
config.change = function(event, ui) {
|
||||
if (!ui.item || !ui.item.actual) {
|
||||
options.value(event.target && event.target.value);
|
||||
|
||||
if (ko.isWriteableObservable(options.dataValue)) {
|
||||
options.dataValue(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (existingChange) {
|
||||
existingChange.apply(this, arguments);
|
||||
}
|
||||
};
|
||||
|
||||
//initialize the widget
|
||||
var widget = $(element).autocomplete(config).data("ui-autocomplete");
|
||||
|
||||
//render a template for the items
|
||||
if (options.template) {
|
||||
widget._renderItem = self.renderItem.bind(self, options.template, context);
|
||||
}
|
||||
|
||||
//destroy the widget if KO removes the element
|
||||
ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
|
||||
if (widget && typeof widget.destroy === "function") {
|
||||
widget.destroy();
|
||||
widget = null;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//the binding's update function. keep value in sync with model
|
||||
this.update = function(element, valueAccessor) {
|
||||
var propNames, sources,
|
||||
options = unwrap(valueAccessor()),
|
||||
value = unwrap(options && options.value);
|
||||
|
||||
if (!value && value !== 0) {
|
||||
value = "";
|
||||
}
|
||||
|
||||
// find the appropriate value for the input
|
||||
sources = unwrap(options.source);
|
||||
propNames = self.getPropertyNames(valueAccessor);
|
||||
|
||||
// if there is local data, then try to determine the appropriate value for the input
|
||||
if ($.isArray(sources) && propNames.value) {
|
||||
value = ko.utils.arrayFirst(sources, function (opt) {
|
||||
return opt[propNames.value] == value;
|
||||
}
|
||||
) || value;
|
||||
}
|
||||
|
||||
if (propNames.input && value && typeof value === "object") {
|
||||
element.value = value[propNames.input];
|
||||
}
|
||||
else {
|
||||
element.value = value;
|
||||
}
|
||||
};
|
||||
|
||||
//if dealing with local data, the default filtering function
|
||||
this.defaultFilter = function(item, term) {
|
||||
term = term && term.toLowerCase();
|
||||
return (item || item === 0) && ko.toJSON(item).toLowerCase().indexOf(term) > -1;
|
||||
};
|
||||
|
||||
//filter/map options to be in a format that autocomplete requires
|
||||
this.processOptions = function(valueAccessor, filter, data, request, response) {
|
||||
var item, index, length,
|
||||
items = unwrap(data) || [],
|
||||
results = [],
|
||||
props = this.getPropertyNames(valueAccessor);
|
||||
|
||||
//filter/map items
|
||||
for (index = 0, length = items.length; index < length; index++) {
|
||||
item = items[index];
|
||||
|
||||
if (!filter || filter(item, request.term)) {
|
||||
results.push({
|
||||
label: props.label ? item[props.label] : item.toString(),
|
||||
value: props.input ? item[props.input] : item.toString(),
|
||||
actual: props.value ? item[props.value] : item,
|
||||
data: item
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//call autocomplete callback to display list
|
||||
response(results);
|
||||
};
|
||||
|
||||
//if specified, use a template to render an item
|
||||
this.renderItem = function(templateName, context, ul, item) {
|
||||
var $li = $("<li></li>").appendTo(ul),
|
||||
itemContext = context.createChildContext(item.data);
|
||||
|
||||
//apply the template binding
|
||||
ko.applyBindingsToNode($li[0], { template: templateName }, itemContext);
|
||||
|
||||
//clean up
|
||||
$li.one("remove", ko.cleanNode.bind(ko, $li[0]));
|
||||
|
||||
return $li;
|
||||
};
|
||||
|
||||
//retrieve the property names to use for the label, input, and value
|
||||
this.getPropertyNames = function(valueAccessor) {
|
||||
var options = ko.toJS(valueAccessor());
|
||||
|
||||
return {
|
||||
label: options.labelProp || options.valueProp,
|
||||
input: options.inputProp || options.labelProp || options.valueProp,
|
||||
value: options.valueProp
|
||||
};
|
||||
};
|
||||
|
||||
//default global options passed into autocomplete widget
|
||||
this.options = {
|
||||
autoFocus: true,
|
||||
delay: 50
|
||||
};
|
||||
};
|
||||
|
||||
ko.bindingHandlers.jqAuto = new JqAuto();
|
||||
});
|
||||
2
web/Scripts/knockout-jqAutocomplete.min.js
vendored
Normal file
2
web/Scripts/knockout-jqAutocomplete.min.js
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
// knockout-jqAutocomplete 0.4.3 | (c) 2015 Ryan Niemeyer | http://www.opensource.org/licenses/mit-license
|
||||
!function(a){"function"==typeof define&&define.amd?define(["knockout","jquery","jquery-ui/autocomplete"],a):a(window.ko,jQuery)}(function(a,b){var c=function(){var c=this,d=a.utils.unwrapObservable;this.init=function(e,f,g,h,i){var j,k,l=d(f()),m={},n="function"==typeof l.filter?l.filter:c.defaultFilter;a.utils.extend(m,c.options),a.utils.extend(m,l.options),m.source="function"!=typeof l.source||a.isObservable(l.source)?c.processOptions.bind(c,f,n,l.source):function(a,b){var d=function(d){c.processOptions(f,null,d,a,b)};l.source.call(i.$data,a.term,d)},j="function"==typeof m.select&&m.select,k="function"==typeof m.change&&m.change,m.select=function(b,c){c.item&&c.item.actual&&(l.value(c.item.actual),a.isWriteableObservable(l.dataValue)&&l.dataValue(c.item.data)),j&&j.apply(this,arguments)},m.change=function(b,c){c.item&&c.item.actual||(l.value(b.target&&b.target.value),a.isWriteableObservable(l.dataValue)&&l.dataValue(null)),k&&k.apply(this,arguments)};var o=b(e).autocomplete(m).data("ui-autocomplete");l.template&&(o._renderItem=c.renderItem.bind(c,l.template,i)),a.utils.domNodeDisposal.addDisposeCallback(e,function(){o&&"function"==typeof o.destroy&&(o.destroy(),o=null)})},this.update=function(e,f){var g,h,i=d(f()),j=d(i&&i.value);j||0===j||(j=""),h=d(i.source),g=c.getPropertyNames(f),b.isArray(h)&&g.value&&(j=a.utils.arrayFirst(h,function(a){return a[g.value]==j})||j),e.value=g.input&&j&&"object"==typeof j?j[g.input]:j},this.defaultFilter=function(b,c){return c=c&&c.toLowerCase(),(b||0===b)&&a.toJSON(b).toLowerCase().indexOf(c)>-1},this.processOptions=function(a,b,c,e,f){var g,h,i,j=d(c)||[],k=[],l=this.getPropertyNames(a);for(h=0,i=j.length;i>h;h++)g=j[h],(!b||b(g,e.term))&&k.push({label:l.label?g[l.label]:g.toString(),value:l.input?g[l.input]:g.toString(),actual:l.value?g[l.value]:g,data:g});f(k)},this.renderItem=function(c,d,e,f){var g=b("<li></li>").appendTo(e),h=d.createChildContext(f.data);return a.applyBindingsToNode(g[0],{template:c},h),g.one("remove",a.cleanNode.bind(a,g[0])),g},this.getPropertyNames=function(b){var c=a.toJS(b());return{label:c.labelProp||c.valueProp,input:c.inputProp||c.labelProp||c.valueProp,value:c.valueProp}},this.options={autoFocus:!0,delay:50}};a.bindingHandlers.jqAuto=new c});
|
||||
|
|
@ -1,6 +1,13 @@
|
|||
var Yavsc = (function(apiBaseUrl){
|
||||
var self = {};
|
||||
|
||||
function dumpprops(obj) {
|
||||
var str = "";
|
||||
for(var k in obj)
|
||||
if (obj.hasOwnProperty(k))
|
||||
str += k + " = " + obj[k] + "\n";
|
||||
return (str); }
|
||||
|
||||
self.apiBaseUrl = (apiBaseUrl || '/api');
|
||||
|
||||
self.showHide = function () {
|
||||
|
|
@ -33,8 +40,11 @@ self.notice = function (msg, msgok) {
|
|||
|
||||
self.onAjaxBadInput = function (data)
|
||||
{
|
||||
if (!data) { Yavsc.notice('no data'); return; }
|
||||
if (!data.responseJSON) { Yavsc.notice('no json data:'+data); return; }
|
||||
if (!Array.isArray(data.responseJSON)) { Yavsc.notice('Bad Input: '+data.responseJSON); return; }
|
||||
$.each(data.responseJSON, function (key, value) {
|
||||
var errspanid = "Err_cr_" + value.key.replace("model.","");
|
||||
var errspanid = "Err_" + value.key;
|
||||
var errspan = document.getElementById(errspanid);
|
||||
if (errspan==null)
|
||||
alert('enoent '+errspanid);
|
||||
|
|
@ -47,9 +57,24 @@ self.notice = function (msg, msgok) {
|
|||
self.onAjaxError = function (xhr, ajaxOptions, thrownError) {
|
||||
if (xhr.status!=400)
|
||||
Yavsc.notice(xhr.status+" : "+xhr.responseText);
|
||||
else Yavsc.notice(false);
|
||||
};
|
||||
|
||||
return self;
|
||||
})();
|
||||
|
||||
$(document).ready(function(){
|
||||
var $window = $(window);
|
||||
$(window).scroll(function() {
|
||||
var $ns = $('#notifications');
|
||||
if ($ns.has('*').length>0) {
|
||||
if ($window.scrollTop()>375) {
|
||||
$ns.css('position','fixed');
|
||||
$ns.css('z-index',2);
|
||||
$ns.css('top',0);
|
||||
}
|
||||
else {
|
||||
$ns.css('position','static');
|
||||
$ns.css('z-index',1);
|
||||
}}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,37 +0,0 @@
|
|||
//
|
||||
// parralax.js
|
||||
//
|
||||
// Author:
|
||||
// Paul Schneider <paul@pschneider.fr>
|
||||
//
|
||||
// Copyright (c) 2015 GNU GPL
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
$(document).ready(function(){
|
||||
var $window = $(window);
|
||||
$(window).scroll(function() {
|
||||
var $ns = $('#notifications');
|
||||
if ($ns.has('*').length>0) {
|
||||
if ($window.scrollTop()>375) {
|
||||
$ns.css('position','fixed');
|
||||
$ns.css('z-index',2);
|
||||
$ns.css('top',0);
|
||||
}
|
||||
else {
|
||||
$ns.css('position','static');
|
||||
$ns.css('z-index',1);
|
||||
}}
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue