Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
typo3
qfq
Commits
2e267044
Commit
2e267044
authored
Mar 15, 2016
by
Carsten Rose
Browse files
Merge remote-tracking branch 'origin/raos_work' into crose_work
parents
b5abdf72
f89d01e2
Changes
18
Hide whitespace changes
Inline
Side-by-side
javascript/src/Element/Element.js
0 → 100644
View file @
2e267044
/**
* @author Rafael Ostertag <rafael.ostertag@math.uzh.ch>
*/
if
(
!
QfqNS
)
{
var
QfqNS
=
{};
}
if
(
!
QfqNS
.
Element
)
{
QfqNS
.
Element
=
{};
}
(
function
(
n
)
{
'
use strict
'
;
n
.
Element
=
function
(
$element
)
{
if
(
!
$element
||
$element
.
length
===
0
)
{
throw
new
Error
(
"
No element
"
);
}
this
.
formGroup
=
new
n
.
FormGroup
(
$element
);
};
/**
*
* @param type
* @returns {boolean}
*
* @protected
*/
n
.
Element
.
prototype
.
isType
=
function
(
type
)
{
var
lowerCaseType
=
type
.
toLowerCase
();
var
isOfType
=
true
;
this
.
formGroup
.
$element
.
each
(
function
()
{
if
(
this
.
hasAttribute
(
'
type
'
))
{
if
(
this
.
getAttribute
(
'
type
'
)
===
lowerCaseType
)
{
return
true
;
}
else
{
isOfType
=
false
;
return
false
;
}
}
else
{
// <select> is not an attribute value, obviously, so check for nodename
if
(
this
.
nodeName
.
toLowerCase
()
===
lowerCaseType
)
{
return
true
;
}
else
if
(
lowerCaseType
===
'
text
'
)
{
return
true
;
}
else
{
isOfType
=
false
;
return
false
;
}
}
});
return
isOfType
;
};
})(
QfqNS
.
Element
);
\ No newline at end of file
javascript/src/Element/FormGroup.js
0 → 100644
View file @
2e267044
/**
* @author Rafael Ostertag <rafael.ostertag@math.uzh.ch>
*/
if
(
!
QfqNS
)
{
var
QfqNS
=
{};
}
if
(
!
QfqNS
.
Element
)
{
QfqNS
.
Element
=
{};
}
(
function
(
n
)
{
'
use strict
'
;
n
.
FormGroup
=
function
(
$enclosedElement
)
{
if
(
!
$enclosedElement
||
$enclosedElement
.
length
===
0
)
{
throw
new
Error
(
"
No enclosed element
"
);
}
this
.
$formGroup
=
this
.
$findFormGroup
(
$enclosedElement
);
this
.
$element
=
this
.
$formGroup
.
find
(
'
input, select
'
);
this
.
$label
=
this
.
$formGroup
.
find
(
'
.control-label
'
);
this
.
$helpBlock
=
this
.
$formGroup
.
find
(
"
.help-block
"
);
};
/**
*
* @param $enclosedElement
* @returns {*}
*
* @private
*/
n
.
FormGroup
.
prototype
.
$findFormGroup
=
function
(
$enclosedElement
)
{
var
$formGroup
=
$enclosedElement
.
closest
(
"
div.form-group
"
);
if
(
!
$formGroup
||
$formGroup
.
length
===
0
)
{
throw
new
Error
(
"
Unable to find Form Group
"
);
}
if
(
$formGroup
.
length
>
1
)
{
throw
new
Error
(
"
enclosed element yields ambiguous form group
"
);
}
return
$formGroup
;
};
n
.
FormGroup
.
prototype
.
hasLabel
=
function
()
{
return
this
.
$label
.
length
>
0
;
};
n
.
FormGroup
.
prototype
.
hasHelpBlock
=
function
()
{
return
this
.
$helpBlock
.
length
>
0
;
};
n
.
FormGroup
.
prototype
.
setEnabled
=
function
(
enabled
)
{
this
.
$element
.
prop
(
'
disabled
'
,
!
enabled
);
};
n
.
FormGroup
.
prototype
.
setReadOnly
=
function
(
readonly
)
{
this
.
$element
.
propr
(
'
readonly
'
,
readonly
);
};
})(
QfqNS
.
Element
);
\ No newline at end of file
javascript/src/Element/Radio.js
0 → 100644
View file @
2e267044
/**
* @author Rafael Ostertag <rafael.ostertag@math.uzh.ch>
*/
if
(
!
QfqNS
)
{
var
QfqNS
=
{};
}
if
(
!
QfqNS
.
Element
)
{
QfqNS
.
Element
=
{};
}
(
function
(
n
)
{
'
use strict
'
;
/**
*
* @param $element
* @constructor
*/
function
Radio
(
$element
)
{
n
.
Element
.
call
(
this
,
$element
);
if
(
!
this
.
isType
(
"
radio
"
))
{
throw
new
Error
(
"
$element is not of type 'radio'
"
);
}
}
Radio
.
prototype
=
Object
.
create
(
n
.
Element
.
prototype
);
Radio
.
prototype
.
constructor
=
Radio
;
Radio
.
prototype
.
setValue
=
function
(
val
)
{
this
.
formGroup
.
$element
.
prop
(
'
checked
'
,
false
);
this
.
formGroup
.
$element
.
filter
(
'
[value=
'
+
val
+
"
]
"
).
prop
(
'
checked
'
,
true
);
};
Radio
.
prototype
.
getValue
=
function
()
{
return
this
.
formGroup
.
$element
.
filter
(
'
:checked
'
).
val
();
};
n
.
Radio
=
Radio
;
})(
QfqNS
.
Element
);
\ No newline at end of file
javascript/src/Element/Select.js
0 → 100644
View file @
2e267044
/**
* @author Rafael Ostertag <rafael.ostertag@math.uzh.ch>
*/
/* global $ */
if
(
!
QfqNS
)
{
var
QfqNS
=
{};
}
if
(
!
QfqNS
.
Element
)
{
QfqNS
.
Element
=
{};
}
(
function
(
n
)
{
'
use strict
'
;
/**
*
* @param $element
* @constructor
*/
function
Select
(
$element
)
{
n
.
Element
.
call
(
this
,
$element
);
if
(
!
this
.
isType
(
"
select
"
))
{
throw
new
Error
(
"
$element is not of type 'select'
"
);
}
}
Select
.
prototype
=
Object
.
create
(
n
.
Element
.
prototype
);
Select
.
prototype
.
constructor
=
Select
;
/**
* Set the value or selection of a `<select>` tag
*
* @param {string|array} val when passing a string, the corresponding <option> tag will get selected. If passed
* array of objects, `<select>` will have its `<option>` tags set correspondingly.
*/
Select
.
prototype
.
setValue
=
function
(
val
)
{
if
(
typeof
(
val
)
in
[
'
string
'
,
'
number
'
])
{
this
.
setSelection
(
val
);
}
else
if
(
Array
.
isArray
(
val
))
{
this
.
formGroup
.
$element
.
empty
();
// Fill array with new <select> elements first and add it to the dom in one step, instead of appending
// each '<select>' separately.
var
selectArray
;
val
.
forEach
(
function
(
selectObj
)
{
var
$option
=
$
(
'
<option>
'
)
.
addAttribute
(
'
value
'
,
selectObj
.
value
?
selectObj
.
value
:
selectObj
.
text
)
.
prop
(
'
selected
'
,
selectObj
.
selected
?
selectObj
.
selected
:
false
)
.
append
(
selectObj
.
text
);
selectArray
.
append
(
$option
);
});
this
.
formGroup
.
$element
.
append
(
selectArray
);
}
else
{
throw
Error
(
'
Unsupported type of argument in Select.setValue: "
'
+
typeof
(
val
)
+
'
". Expected either
'
+
'
"string" or "array"
'
);
}
};
/**
*
* @param val
*
* @private
*/
Select
.
prototype
.
setSelection
=
function
(
val
)
{
this
.
clearSelection
();
// First, see if we find an <option> tag having an attribute 'value' matching val. If that doesn't work,
// fall back to comparing text content of <option> tags.
var
$selectionByValue
=
this
.
formGroup
.
$element
.
find
(
'
option[value=
'
+
val
);
if
(
$selectionByValue
.
length
>
0
)
{
$selectionByValue
.
prop
(
'
selected
'
,
true
);
}
else
{
this
.
formGroup
.
$element
.
find
(
'
option
'
).
each
(
function
()
{
var
$element
=
$
(
this
);
if
(
$element
.
text
()
===
val
)
{
$element
.
prop
(
'
selected
'
,
true
);
}
return
true
;
});
}
};
/**
* @private
*/
Select
.
prototype
.
clearSelection
=
function
()
{
this
.
formGroup
.
$element
.
find
(
'
:selected
'
).
each
(
function
()
{
$
(
this
).
prop
(
'
selected
'
,
false
);
});
};
Select
.
prototype
.
getValue
=
function
()
{
var
returnValue
=
[];
this
.
formGroup
.
$element
.
find
(
'
:selected
'
).
each
(
function
()
{
if
(
this
.
hasAttribute
(
'
value
'
))
{
returnValue
.
push
(
this
.
getAttribute
(
'
value
'
));
}
else
{
returnValue
.
push
(
$
(
this
).
text
());
}
}
);
return
returnValue
;
};
n
.
Select
=
Select
;
})(
QfqNS
.
Element
);
\ No newline at end of file
javascript/src/Element/Text.js
0 → 100644
View file @
2e267044
/**
* @author Rafael Ostertag <rafael.ostertag@math.uzh.ch>
*/
if
(
!
QfqNS
)
{
var
QfqNS
=
{};
}
if
(
!
QfqNS
.
Element
)
{
QfqNS
.
Element
=
{};
}
(
function
(
n
)
{
'
use strict
'
;
/**
*
* @param $element
* @constructor
*/
function
Input
(
$element
)
{
n
.
Element
.
call
(
this
,
$element
);
if
(
!
this
.
isType
(
"
text
"
))
{
throw
new
Error
(
"
$element is not of type 'text'
"
);
}
}
Input
.
prototype
=
Object
.
create
(
n
.
Element
.
prototype
);
Input
.
prototype
.
constructor
=
Input
;
Input
.
prototype
.
setValue
=
function
(
val
)
{
this
.
formGroup
.
$element
.
val
(
val
);
};
Input
.
prototype
.
getValue
=
function
()
{
return
this
.
formGroup
.
$element
.
val
();
};
n
.
Input
=
Input
;
})(
QfqNS
.
Element
);
\ No newline at end of file
javascript/src/Element/data.js
0 → 100644
View file @
2e267044
/**
* @author Rafael Ostertag <rafael.ostertag@math.uzh.ch>
*/
if
(
!
QfqNS
)
{
var
QfqNS
=
{};
}
if
(
!
QfqNS
.
Element
)
{
QfqNS
.
Element
=
{};
}
(
function
(
n
)
{
'
use strict
'
;
/**
* Known values of `type` attribute of `<input>` elements
*
* @type {string[]}
*/
n
.
knownElementTypes
=
[
'
text
'
,
'
password
'
,
'
checkbox
'
,
'
radio
'
,
'
button
'
,
'
submit
'
,
'
reset
'
,
'
file
'
,
'
hidden
'
,
'
image
'
,
'
datetime
'
,
'
datetime-local
'
,
'
date
'
,
'
month
'
,
'
time
'
,
'
week
'
,
'
number
'
,
'
range
'
,
'
email
'
,
'
url
'
,
'
search
'
,
'
tel
'
,
'
color
'
];
})(
QfqNS
.
Element
);
\ No newline at end of file
javascript/src/QfqRecordList.js
0 → 100644
View file @
2e267044
/**
* @author Rafael Ostertag <rafael.ostertag@math.uzh.ch>
*/
/* global $ */
/* global console */
if
(
!
QfqNS
)
{
var
QfqNS
=
{};
}
(
function
(
n
)
{
'
use strict
'
;
n
.
QfqRecordList
=
function
(
deleteUrl
)
{
this
.
deleteUrl
=
deleteUrl
;
this
.
deleteButtonClass
=
'
record-delete
'
;
this
.
recordClass
=
'
record
'
;
this
.
sipDataAttribute
=
'
sip
'
;
this
.
connectClickHandler
();
};
/**
* @private
*/
n
.
QfqRecordList
.
prototype
.
connectClickHandler
=
function
()
{
$
(
"
.
"
+
this
.
deleteButtonClass
).
click
(
this
.
handleDeleteButtonClick
.
bind
(
this
));
};
n
.
QfqRecordList
.
prototype
.
handleDeleteButtonClick
=
function
(
event
)
{
var
$eventTarget
=
$
(
event
.
target
);
var
$recordElement
=
this
.
getRecordElement
(
event
.
target
);
if
(
$recordElement
.
length
!==
1
)
{
throw
new
Error
(
$recordElement
.
length
+
'
match(es) found for record class
'
);
}
var
sip
=
$eventTarget
.
data
(
'
sip
'
);
if
(
!
sip
)
{
throw
new
Error
(
'
No `sip` on delete button
'
);
}
var
alert
=
new
QfqNS
.
Alert
(
"
Do you really want to delete the record?
"
,
"
warning
"
,
"
yesno
"
);
var
that
=
this
;
alert
.
addOkButtonHandler
(
function
()
{
$
.
post
(
that
.
deleteUrl
+
"
?s=
"
+
sip
)
.
done
(
that
.
ajaxDeleteSuccessDispatcher
.
bind
(
that
,
$recordElement
))
.
fail
(
that
.
ajaxDeleteFailureHandler
.
bind
(
that
));
});
alert
.
show
();
};
/**
*
* @param originatingEvent
* @param data
* @param textStatus
* @param jqXHR
*
* @private
*/
n
.
QfqRecordList
.
prototype
.
ajaxDeleteSuccessDispatcher
=
function
(
$recordElement
,
data
,
textStatus
,
jqXHR
)
{
if
(
!
data
.
status
)
{
throw
new
Error
(
"
No 'status' property 'data'
"
);
}
switch
(
data
.
status
)
{
case
"
error
"
:
this
.
handleLogicDeleteError
(
data
);
break
;
case
"
success
"
:
this
.
handleDeleteSuccess
(
$recordElement
,
data
);
break
;
default
:
throw
new
Error
(
"
Status '
"
+
data
.
status
+
"
' unknown.
"
);
}
};
n
.
QfqRecordList
.
prototype
.
handleDeleteSuccess
=
function
(
$recordElement
,
data
)
{
if
(
data
.
redirect
&&
data
.
redirect
===
"
url
"
&&
data
[
'
redirect-url
'
])
{
window
.
location
=
data
[
'
redirect-url
'
];
return
;
}
if
(
data
.
redirect
&&
data
.
redirect
===
"
no
"
)
{
var
alert
=
new
QfqNS
.
Alert
(
"
redirect=='no' not allowed
"
,
"
error
"
);
alert
.
show
();
}
$recordElement
.
fadeOut
(
400
,
function
()
{
$recordElement
.
remove
();
});
};
n
.
QfqRecordList
.
prototype
.
ajaxDeleteFailureHandler
=
function
(
jqXHR
,
textStatus
,
errorThrown
)
{
var
alert
=
new
QfqNS
.
Alert
(
"
Error:<br>
"
+
errorThrown
,
"
error
"
);
alert
.
show
();
};
n
.
QfqRecordList
.
prototype
.
getRecordElement
=
function
(
element
)
{
return
$
(
element
).
closest
(
'
.
'
+
this
.
recordClass
);
};
/**
*
* @param data
*
* @private
*/
n
.
QfqRecordList
.
prototype
.
handleLogicDeleteError
=
function
(
data
)
{
if
(
!
data
.
message
)
{
throw
Error
(
"
Status is 'error' but required 'message' attribute is missing.
"
);
}
var
alert
=
new
QfqNS
.
Alert
(
data
.
message
,
"
error
"
);
alert
.
show
();
};
})(
QfqNS
);
\ No newline at end of file
less/qfq-bs.css.less
View file @
2e267044
#qfqAlertContainer {
position:
absolute
;
position:
fixed
;
top: 0;
left: 0;
width: 100%;
z-index: 1000;
}
/*inline elements in horizontal mode are too much left*/
...
...
mockup/api/delete_list_ok.json
0 → 100644
View file @
2e267044
{
"status"
:
"success"
,
"message"
:
"successfully deleted item"
,
"redirect"
:
"client"
}
\ No newline at end of file
mockup/personmock.html
View file @
2e267044
...
...
@@ -9,7 +9,7 @@
<link
rel=
"stylesheet"
href=
"../css/bootstrap-theme.min.css"
>
<link
rel=
"stylesheet"
href=
"../css/jqx.base.css"
>
<link
rel=
"stylesheet"
href=
"../css/jqx.darkblue.css"
>
<link
rel=
"stylesheet"
href=
"../css/qfq-
jqw
.css"
>
<link
rel=
"stylesheet"
href=
"../css/qfq-
bs
.css"
>
<title>
Person Form Mockup
</title>
...
...
@@ -179,12 +179,12 @@
<div
class=
"col-md-6"
>
<div
class=
"radio"
>
<label>
<input
type=
"radio"
>
male
<input
type=
"radio"
name=
"gender"
>
male
</label>
</div>
<div
class=
"radio"
>
<label>
<input
type=
"radio"
>
female
<input
type=
"radio"
name=
"gender"
>
female
</label>
</div>
</div>
...
...
@@ -738,7 +738,7 @@
<script
src=
"../js/jquery.min.js"
></script>
<script
src=
"../js/bootstrap.min.js"
></script>
<script
src=
"../js/jqx-all.js"
></script>
<script
src=
"../js/qfq
-jqw
.debug.js"
></script>
<script
src=
"../js/qfq.debug.js"
></script>
<script
type=
"text/javascript"
>
$
(
function
()
{
...
...
mockup/recordlist.html
0 → 100644
View file @
2e267044
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<meta
charset=
"UTF-8"
>
<link
rel=
"stylesheet"
href=
"../css/bootstrap.min.css"
>
<link
rel=
"stylesheet"
href=
"../css/bootstrap-theme.min.css"
>
<link
rel=
"stylesheet"
href=
"../css/jqx.base.css"
>
<link
rel=
"stylesheet"
href=
"../css/jqx.darkblue.css"
>
<link
rel=
"stylesheet"
href=
"../css/qfq-bs.css"
>
<title></title>
</head>
<body>
<label>
Delete to
<select
name=
"deleteTo"
id=
"deleteTo"
>
<option>
404 error
</option>
<option>
delete_list_ok.json
</option>
</select>
</label>
<table>
<tr>
<th>
Head1
</th>
<th>
Head2
</th>
<th></th>
</tr>
<tr
class=
"record"
>
<td>
1
</td>
<td>
a
</td>
<td>
<button
data-sip=
"1"
class=
"record-delete"
>
Delete
</button>
</td>
</tr>
<tr
class=
"record"
>
<td>
2
</td>
<td>
b
</td>
<td>
<button
data-sip=
"2"
class=
"record-delete"
>
Delete
</button>
</td>
</tr>
<tr
class=
"record"
>
<td>
3
</td>
<td>
c
</td>
<td>
<button
data-sip=
"3"
class=
"record-delete"
>
Delete
</button>
</td>
</tr>
<tr
class=
"record"
>
<td>
4
</td>
<td>
d
</td>
<td>
<button
data-sip=
"4"
class=