在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:ermouth/jQuery.my开源软件地址:https://github.com/ermouth/jQuery.my开源编程语言:JavaScript 100.0%开源软件介绍:jQuery.myBelow API description is not complete, see jquerymy.com for more detailed API, examples and list of compatible controls. jquerymy is a plugin for complex reactive two-way data binding between DOM and nested JS state objects. jquerymy recognizes standard HTML controls as well as composite controls rendered by jQuery Mobile, nearly all jQuery UI widgets, Redactor, Ace, CodeMirror, Select2 and others. jquerymy provides comprehensive validation, conditional formatting and dependencies resolution. Apps can be nested – each $.my instance can be used as control in a parent form, if any. jquerymy also incorporates simple template engine and modal dialog mechanics. See cloudwall.me as an example of web-app platform built on top of $.my. Also good example of a very large jquerymy app is Photon, an unofficial administrative panel for CouchDB. SetupjQuery.my requires jQuery 2.0+ and SugarJS 1.3.9–1.4.1. <script src="/js/sugar.min.js"></script>
<script src="/js/jquery.min.js"></script>
<script src="/js/jquerymy.min.js"></script> $.my can can be installed from npm – Quick startvar person={};
var manifest = {
"data": { name:"", metrics:{ age:"" }},
"init": function ($node, formRuntimeObj) {
$node.html(
'<div><input id="name" type="text" /></div>' +
'<div><input id="age" type="number" /></div>'
);
},
"ui":{
"#name": { bind: "name" },
"#age" : { bind: "metrics.age" }
}
};
// Init $.my
$("#form").my(manifest, person); Now form inputs are filled with init values and any interaction with controls immediately mutates First param passed to $.my is denoted below as manifest. Retrieving and updating dataTo get form data just read value of the To put new data into already initialized instance of $.my call More complex data bindThe So $("#form").my({
ui:{
"#name": "name",
"#age" : {
bind: function (data, value, $control) {
if (value != null) data.metrics.age = value;
return data.metrics.age =
(data.metrics.age + "").replace(/\D/g,"");
}
}
}
}, person); Note bind function in example won't allow to input anything than number. Pressing non-num key will do nothing with input, non-num chars are stripped immediately. Third param ValidationThere are several ways to validate data received from control. Validator can be a regexp or a function. Functions unlike regexps can return custom error messages depending on value being checked. Check is performed just before executing If value is incorrect If control is not interactive – we bind some data with RegExp validation$("#form").my({
ui:{
"#name": {
bind: "name",
check:/^[a-z]{10}$/i,
error:"10 latin chars" // Optional
},
"#age": { bind: "metrics.age" }
}
}); If user puts something other than 10-letter combination into Validating with functionValidator function receives same params as Unlike $("#form").my({
data:{/*...*/},
init: function ($node){/*...*/},
ui:{
"#name": {
"bind": "name",
"check": function (data, value, $control) {
if (value.length > 20) return "Too long name";
if (!/^[a-z]+$/.test(value)) return "Only letters allowed";
return "";
}
},
"#age": "age"
}
}); Messages returned by validator are put into DOM element with class <div>
<input id="name" type="text" />
<span class="my-error-tip"></span>
</div> Checking entire form has no errors
To spot whether entire data is valid call DependenciesLet it be a form that calculates product of two values. We need to recalculate product each time any of factors changes. $("#form").my({
data:{ num1:"10", num2:"1.5" },
init: function ($node){/*...*/},
ui:{
"#factor1": "num1",
"#factor2": "num2",
"#product": {
bind: function (data) {
return data.num1 * data.num2;
},
watch: "#factor1,#factor2" //shorthand for ["#factor1", "#factor2"]
}
}
}); Product is not mapped to data – There is another syntax to define dependencies. $("#form").my({
ui:{
"#factor1": {
bind: "num1",
recalc: "#product"
},
"#factor2": "num2",
"#product": {
bind: function (data) {return data.num1 * data.num2},
watch: "#factor2"
}
}
}); It behaves the same way. Note that Loop dependencies are resolved correctly. Conditional formatting and disabling$.my can apply different classes depending on data object state. $("#form").my({
ui:{
"#name": {
bind: "name",
recalc: "#age",
css: {
"orange":/^.{10}$/
}
},
"#age": {
bind: "age",
css:{
":disabled": function (data, value) {
return data.name.length == 0;
}
}
}
}
}); Here if Input Conditional formatting over appropriate field is applied after Init functionsPreparing form during initialization$("#form").my({
data: { range: [30, 70] },
init: function ($node) {
$node.html('<input id="range" />')
},
ui:{
"#range": {
init: function ($control) {
$control.slider(range: true, min: 0, max: 100);
},
bind: "range"
}
}
}); Here we apply jQuery.UI Slider plugin over Certainly HTML carcass itself can be generated using Async initTo become async $("#form")
.my({
data: { name:"" },
init: function ($node, runtime) {
var promise = $.ajax({
url:"http://some.url"
}).then(function (res) {
// We received response, gen form HTML
$node.html('<input id="name" type="text"/>')
// Assume res is string, mount default data
runtime.data.name = res;
});
return promise;
},
ui:{"#name": "name"}
})
.then(function (data){
// Do something when form init finished
})
.fail(function(errMessage) {
// Do something if init failed
}); jQuery AJAX implementation returns promise, so we may return Nested and repeated formsEach DOM node which was instantiated with $("#form")
.my({
data: { name:"" , child:{}},
init: function ($node, runtime) {
//Draw HTML
},
ui:{
"#name": "name",
"#child" :{
bind:"child",
check:true, //ensures child’s errors invalidate parent
manifest:{
data:{/* child’s data struct */},
init:{/* child’s init, can be async */},
ui:{ /* child’s ui */}
}
}
}
}) To build list of nested forms just bind it with array. Below example builds list of similar array elements. $("#form")
.my({
data: { name:"" , child:[ /* array of elts */]},
init: function ($node, runtime) {
//Draw HTML
},
ui:{
"#name": "name",
"#child" :{
bind:"child",
check:true,
list:'<div class="someClass"></div>', //optional
init: function ($list) { //optional
// Makes list items sortable by drag
// and drop, jQuery UI plugin required
$list.sortable();
},
manifest:{
data:{/* child’s data struct */},
init:{/* child’s init, can be async */},
ui:{ /* child’s ui */}
},
}
}
}) Tuning behaviorEvents$.my understands many types of controls and automatically selects appropriate event handler(s) to provide real-time binding. It’s a kind of device driver for different plugins and conventional HTML inputs or noninteractive elements. But sometimes you need no realtime response – in case of buttons or links for example. Bind function must be executed only when button is really clicked, not while initializing. $("#form").my({
ui:{
"#button": {
bind: function (data, value) {
if (value != null) {
//do something
}
},
events: "click,dblclick"
}
}
}); The DelaysThere are several cases bind function must have kind of an anti-jitter. If control is jQuery.UI Slider or conventional HTML5 $("#form").my({
ui:{
"#slider": {
bind: function (data, val) { /* do somth*/ },
delay: 150
}
}
}); In this example Reusable code snippetsSome functions or fields inside manifest can contain code with matching fragments. It can be same regexps for different fields, or some dictionaries used here and there etc. They can be stored at manifest's root and acessed from $("#form").my({
NumCheck:/^\d+$/,
ForbiddenPasswords:["123","qwerty"],
ui:{
"#num": {
bind: "num",
check: "NumCheck"
},
"#pwd":{
bind:"password",
check: function (data, value) {
var pwdList = this.ForbiddenPasswords;
if (pwdList.indexOf(value) == -1) return "Too simple password!";
return "";
}
}
},
SomeFunction: function () { // this points to runtime manifest }
}); Not only checks but every function defined in Manifest deliveryThere is buil-in method to convert manifest with functions and regexps into conventional JSON. It's useful for on-demand manifest delivery using ajax calls. This approach is used in CouchDB to store internal functions as JSON docs. It's quite simple and straightforward.
Method There is no need to decipher encoded manifests before passing them to $.my – they are unwinded automatically. Styling formsManifest can contain {
id:"ManifestId",
data:{...},
init function(){...}
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论