Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
D
douban-api-proxy
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
captainwong
douban-api-proxy
Commits
cd0aeb28
Commit
cd0aeb28
authored
Mar 28, 2016
by
Cervinko Cera
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Typeahead for Author input
parent
d979ed89
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
657 additions
and
10 deletions
+657
-10
typeaheadjs.css
cps/static/css/typeaheadjs.css
+93
-0
bootstrap3-typeahead.js
cps/static/js/bootstrap3-typeahead.js
+523
-0
edit_book.html
cps/templates/edit_book.html
+21
-1
layout.html
cps/templates/layout.html
+11
-9
web.py
cps/web.py
+9
-0
No files found.
cps/static/css/typeaheadjs.css
0 → 100644
View file @
cd0aeb28
span
.twitter-typeahead
.tt-menu
,
span
.twitter-typeahead
.tt-dropdown-menu
{
position
:
absolute
;
top
:
100%
;
left
:
0
;
z-index
:
1000
;
display
:
none
;
float
:
left
;
min-width
:
160px
;
padding
:
5px
0
;
margin
:
2px
0
0
;
list-style
:
none
;
font-size
:
14px
;
text-align
:
left
;
background-color
:
#ffffff
;
border
:
1px
solid
#cccccc
;
border
:
1px
solid
rgba
(
0
,
0
,
0
,
0.15
);
border-radius
:
4px
;
-webkit-box-shadow
:
0
6px
12px
rgba
(
0
,
0
,
0
,
0.175
);
box-shadow
:
0
6px
12px
rgba
(
0
,
0
,
0
,
0.175
);
background-clip
:
padding-box
;
}
span
.twitter-typeahead
.tt-suggestion
{
display
:
block
;
padding
:
3px
20px
;
clear
:
both
;
font-weight
:
normal
;
line-height
:
1.42857143
;
color
:
#333333
;
white-space
:
nowrap
;
}
span
.twitter-typeahead
.tt-suggestion.tt-cursor
,
span
.twitter-typeahead
.tt-suggestion
:hover
,
span
.twitter-typeahead
.tt-suggestion
:focus
{
color
:
#ffffff
;
text-decoration
:
none
;
outline
:
0
;
background-color
:
#337ab7
;
}
.input-group.input-group-lg
span
.twitter-typeahead
.form-control
{
height
:
46px
;
padding
:
10px
16px
;
font-size
:
18px
;
line-height
:
1.3333333
;
border-radius
:
6px
;
}
.input-group.input-group-sm
span
.twitter-typeahead
.form-control
{
height
:
30px
;
padding
:
5px
10px
;
font-size
:
12px
;
line-height
:
1.5
;
border-radius
:
3px
;
}
span
.twitter-typeahead
{
width
:
100%
;
}
.input-group
span
.twitter-typeahead
{
display
:
block
!important
;
height
:
34px
;
}
.input-group
span
.twitter-typeahead
.tt-menu
,
.input-group
span
.twitter-typeahead
.tt-dropdown-menu
{
top
:
32px
!important
;
}
.input-group
span
.twitter-typeahead
:not
(
:first-child
)
:not
(
:last-child
)
.form-control
{
border-radius
:
0
;
}
.input-group
span
.twitter-typeahead
:first-child
.form-control
{
border-top-left-radius
:
4px
;
border-bottom-left-radius
:
4px
;
border-top-right-radius
:
0
;
border-bottom-right-radius
:
0
;
}
.input-group
span
.twitter-typeahead
:last-child
.form-control
{
border-top-left-radius
:
0
;
border-bottom-left-radius
:
0
;
border-top-right-radius
:
4px
;
border-bottom-right-radius
:
4px
;
}
.input-group.input-group-sm
span
.twitter-typeahead
{
height
:
30px
;
}
.input-group.input-group-sm
span
.twitter-typeahead
.tt-menu
,
.input-group.input-group-sm
span
.twitter-typeahead
.tt-dropdown-menu
{
top
:
30px
!important
;
}
.input-group.input-group-lg
span
.twitter-typeahead
{
height
:
46px
;
}
.input-group.input-group-lg
span
.twitter-typeahead
.tt-menu
,
.input-group.input-group-lg
span
.twitter-typeahead
.tt-dropdown-menu
{
top
:
46px
!important
;
}
cps/static/js/bootstrap3-typeahead.js
0 → 100644
View file @
cd0aeb28
/* =============================================================
* bootstrap3-typeahead.js v3.1.0
* https://github.com/bassjobsen/Bootstrap-3-Typeahead
* =============================================================
* Original written by @mdo and @fat
* =============================================================
* Copyright 2014 Bass Jobsen @bassjobsen
*
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an 'AS IS' BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============================================================ */
(
function
(
root
,
factory
)
{
'use strict'
;
// CommonJS module is defined
if
(
typeof
module
!==
'undefined'
&&
module
.
exports
)
{
module
.
exports
=
factory
(
require
(
'jquery'
));
}
// AMD module is defined
else
if
(
typeof
define
===
'function'
&&
define
.
amd
)
{
define
([
'jquery'
],
function
(
$
)
{
return
factory
(
$
);
});
}
else
{
factory
(
root
.
jQuery
);
}
}(
this
,
function
(
$
)
{
'use strict'
;
// jshint laxcomma: true
/* TYPEAHEAD PUBLIC CLASS DEFINITION
* ================================= */
var
Typeahead
=
function
(
element
,
options
)
{
this
.
$element
=
$
(
element
);
this
.
options
=
$
.
extend
({},
$
.
fn
.
typeahead
.
defaults
,
options
);
this
.
matcher
=
this
.
options
.
matcher
||
this
.
matcher
;
this
.
sorter
=
this
.
options
.
sorter
||
this
.
sorter
;
this
.
select
=
this
.
options
.
select
||
this
.
select
;
this
.
autoSelect
=
typeof
this
.
options
.
autoSelect
==
'boolean'
?
this
.
options
.
autoSelect
:
true
;
this
.
highlighter
=
this
.
options
.
highlighter
||
this
.
highlighter
;
this
.
render
=
this
.
options
.
render
||
this
.
render
;
this
.
updater
=
this
.
options
.
updater
||
this
.
updater
;
this
.
displayText
=
this
.
options
.
displayText
||
this
.
displayText
;
this
.
source
=
this
.
options
.
source
;
this
.
delay
=
this
.
options
.
delay
;
this
.
$menu
=
$
(
this
.
options
.
menu
);
this
.
$appendTo
=
this
.
options
.
appendTo
?
$
(
this
.
options
.
appendTo
)
:
null
;
this
.
shown
=
false
;
this
.
listen
();
this
.
showHintOnFocus
=
typeof
this
.
options
.
showHintOnFocus
==
'boolean'
?
this
.
options
.
showHintOnFocus
:
false
;
this
.
afterSelect
=
this
.
options
.
afterSelect
;
this
.
addItem
=
false
;
};
Typeahead
.
prototype
=
{
constructor
:
Typeahead
,
select
:
function
()
{
var
val
=
this
.
$menu
.
find
(
'.active'
).
data
(
'value'
);
this
.
$element
.
data
(
'active'
,
val
);
if
(
this
.
autoSelect
||
val
)
{
var
newVal
=
this
.
updater
(
val
);
// Updater can be set to any random functions via "options" parameter in constructor above.
// Add null check for cases when updater returns void or undefined.
if
(
!
newVal
)
{
newVal
=
""
;
}
this
.
$element
.
val
(
this
.
displayText
(
newVal
)
||
newVal
)
.
change
();
this
.
afterSelect
(
newVal
);
}
return
this
.
hide
();
},
updater
:
function
(
item
)
{
return
item
;
},
setSource
:
function
(
source
)
{
this
.
source
=
source
;
},
show
:
function
()
{
var
pos
=
$
.
extend
({},
this
.
$element
.
position
(),
{
height
:
this
.
$element
[
0
].
offsetHeight
}),
scrollHeight
;
scrollHeight
=
typeof
this
.
options
.
scrollHeight
==
'function'
?
this
.
options
.
scrollHeight
.
call
()
:
this
.
options
.
scrollHeight
;
var
element
;
if
(
this
.
shown
)
{
element
=
this
.
$menu
;
}
else
if
(
this
.
$appendTo
)
{
element
=
this
.
$menu
.
appendTo
(
this
.
$appendTo
);
}
else
{
element
=
this
.
$menu
.
insertAfter
(
this
.
$element
);
}
element
.
css
({
top
:
pos
.
top
+
pos
.
height
+
scrollHeight
,
left
:
pos
.
left
})
.
show
();
this
.
shown
=
true
;
return
this
;
},
hide
:
function
()
{
this
.
$menu
.
hide
();
this
.
shown
=
false
;
return
this
;
},
lookup
:
function
(
query
)
{
var
items
;
if
(
typeof
(
query
)
!=
'undefined'
&&
query
!==
null
)
{
this
.
query
=
query
;
}
else
{
this
.
query
=
this
.
$element
.
val
()
||
''
;
}
if
(
this
.
query
.
length
<
this
.
options
.
minLength
&&
!
this
.
options
.
showHintOnFocus
)
{
return
this
.
shown
?
this
.
hide
()
:
this
;
}
var
worker
=
$
.
proxy
(
function
()
{
if
(
$
.
isFunction
(
this
.
source
))
this
.
source
(
this
.
query
,
$
.
proxy
(
this
.
process
,
this
));
else
if
(
this
.
source
)
{
this
.
process
(
this
.
source
);
}
},
this
);
clearTimeout
(
this
.
lookupWorker
);
this
.
lookupWorker
=
setTimeout
(
worker
,
this
.
delay
);
},
process
:
function
(
items
)
{
var
that
=
this
;
items
=
$
.
grep
(
items
,
function
(
item
)
{
return
that
.
matcher
(
item
);
});
items
=
this
.
sorter
(
items
);
if
(
!
items
.
length
&&
!
this
.
options
.
addItem
)
{
return
this
.
shown
?
this
.
hide
()
:
this
;
}
if
(
items
.
length
>
0
)
{
this
.
$element
.
data
(
'active'
,
items
[
0
]);
}
else
{
this
.
$element
.
data
(
'active'
,
null
);
}
// Add item
if
(
this
.
options
.
addItem
){
items
.
push
(
this
.
options
.
addItem
);
}
if
(
this
.
options
.
items
==
'all'
)
{
return
this
.
render
(
items
).
show
();
}
else
{
return
this
.
render
(
items
.
slice
(
0
,
this
.
options
.
items
)).
show
();
}
},
matcher
:
function
(
item
)
{
var
it
=
this
.
displayText
(
item
);
return
~
it
.
toLowerCase
().
indexOf
(
this
.
query
.
toLowerCase
());
},
sorter
:
function
(
items
)
{
var
beginswith
=
[]
,
caseSensitive
=
[]
,
caseInsensitive
=
[]
,
item
;
while
((
item
=
items
.
shift
()))
{
var
it
=
this
.
displayText
(
item
);
if
(
!
it
.
toLowerCase
().
indexOf
(
this
.
query
.
toLowerCase
()))
beginswith
.
push
(
item
);
else
if
(
~
it
.
indexOf
(
this
.
query
))
caseSensitive
.
push
(
item
);
else
caseInsensitive
.
push
(
item
);
}
return
beginswith
.
concat
(
caseSensitive
,
caseInsensitive
);
},
highlighter
:
function
(
item
)
{
var
html
=
$
(
'<div></div>'
);
var
query
=
this
.
query
;
var
i
=
item
.
toLowerCase
().
indexOf
(
query
.
toLowerCase
());
var
len
,
leftPart
,
middlePart
,
rightPart
,
strong
;
len
=
query
.
length
;
if
(
len
===
0
){
return
html
.
text
(
item
).
html
();
}
while
(
i
>
-
1
)
{
leftPart
=
item
.
substr
(
0
,
i
);
middlePart
=
item
.
substr
(
i
,
len
);
rightPart
=
item
.
substr
(
i
+
len
);
strong
=
$
(
'<strong></strong>'
).
text
(
middlePart
);
html
.
append
(
document
.
createTextNode
(
leftPart
))
.
append
(
strong
);
item
=
rightPart
;
i
=
item
.
toLowerCase
().
indexOf
(
query
.
toLowerCase
());
}
return
html
.
append
(
document
.
createTextNode
(
item
)).
html
();
},
render
:
function
(
items
)
{
var
that
=
this
;
var
self
=
this
;
var
activeFound
=
false
;
var
data
=
[];
var
_category
=
that
.
options
.
separator
;
$
.
each
(
items
,
function
(
key
,
value
)
{
// inject separator
if
(
key
>
0
&&
value
[
_category
]
!==
items
[
key
-
1
][
_category
]){
data
.
push
({
__type
:
'divider'
});
}
// inject category header
if
(
value
[
_category
]
&&
(
key
===
0
||
value
[
_category
]
!==
items
[
key
-
1
][
_category
])){
data
.
push
({
__type
:
'category'
,
name
:
value
[
_category
]
});
}
data
.
push
(
value
);
});
items
=
$
(
data
).
map
(
function
(
i
,
item
)
{
if
((
item
.
__type
||
false
)
==
'category'
){
return
$
(
that
.
options
.
headerHtml
).
text
(
item
.
name
)[
0
];
}
if
((
item
.
__type
||
false
)
==
'divider'
){
return
$
(
that
.
options
.
headerDivider
)[
0
];
}
var
text
=
self
.
displayText
(
item
);
i
=
$
(
that
.
options
.
item
).
data
(
'value'
,
item
);
i
.
find
(
'a'
).
html
(
that
.
highlighter
(
text
,
item
));
if
(
text
==
self
.
$element
.
val
())
{
i
.
addClass
(
'active'
);
self
.
$element
.
data
(
'active'
,
item
);
activeFound
=
true
;
}
return
i
[
0
];
});
if
(
this
.
autoSelect
&&
!
activeFound
)
{
items
.
filter
(
':not(.dropdown-header)'
).
first
().
addClass
(
'active'
);
this
.
$element
.
data
(
'active'
,
items
.
first
().
data
(
'value'
));
}
this
.
$menu
.
html
(
items
);
return
this
;
},
displayText
:
function
(
item
)
{
return
typeof
item
!==
'undefined'
&&
typeof
item
.
name
!=
'undefined'
&&
item
.
name
||
item
;
},
next
:
function
(
event
)
{
var
active
=
this
.
$menu
.
find
(
'.active'
).
removeClass
(
'active'
)
,
next
=
active
.
next
();
if
(
!
next
.
length
)
{
next
=
$
(
this
.
$menu
.
find
(
'li'
)[
0
]);
}
next
.
addClass
(
'active'
);
},
prev
:
function
(
event
)
{
var
active
=
this
.
$menu
.
find
(
'.active'
).
removeClass
(
'active'
)
,
prev
=
active
.
prev
();
if
(
!
prev
.
length
)
{
prev
=
this
.
$menu
.
find
(
'li'
).
last
();
}
prev
.
addClass
(
'active'
);
},
listen
:
function
()
{
this
.
$element
.
on
(
'focus'
,
$
.
proxy
(
this
.
focus
,
this
))
.
on
(
'blur'
,
$
.
proxy
(
this
.
blur
,
this
))
.
on
(
'keypress'
,
$
.
proxy
(
this
.
keypress
,
this
))
.
on
(
'input'
,
$
.
proxy
(
this
.
input
,
this
))
.
on
(
'keyup'
,
$
.
proxy
(
this
.
keyup
,
this
));
if
(
this
.
eventSupported
(
'keydown'
))
{
this
.
$element
.
on
(
'keydown'
,
$
.
proxy
(
this
.
keydown
,
this
));
}
this
.
$menu
.
on
(
'click'
,
$
.
proxy
(
this
.
click
,
this
))
.
on
(
'mouseenter'
,
'li'
,
$
.
proxy
(
this
.
mouseenter
,
this
))
.
on
(
'mouseleave'
,
'li'
,
$
.
proxy
(
this
.
mouseleave
,
this
));
},
destroy
:
function
()
{
this
.
$element
.
data
(
'typeahead'
,
null
);
this
.
$element
.
data
(
'active'
,
null
);
this
.
$element
.
off
(
'focus'
)
.
off
(
'blur'
)
.
off
(
'keypress'
)
.
off
(
'input'
)
.
off
(
'keyup'
);
if
(
this
.
eventSupported
(
'keydown'
))
{
this
.
$element
.
off
(
'keydown'
);
}
this
.
$menu
.
remove
();
},
eventSupported
:
function
(
eventName
)
{
var
isSupported
=
eventName
in
this
.
$element
;
if
(
!
isSupported
)
{
this
.
$element
.
setAttribute
(
eventName
,
'return;'
);
isSupported
=
typeof
this
.
$element
[
eventName
]
===
'function'
;
}
return
isSupported
;
},
move
:
function
(
e
)
{
if
(
!
this
.
shown
)
return
;
switch
(
e
.
keyCode
)
{
case
9
:
// tab
case
13
:
// enter
case
27
:
// escape
e
.
preventDefault
();
break
;
case
38
:
// up arrow
// with the shiftKey (this is actually the left parenthesis)
if
(
e
.
shiftKey
)
return
;
e
.
preventDefault
();
this
.
prev
();
break
;
case
40
:
// down arrow
// with the shiftKey (this is actually the right parenthesis)
if
(
e
.
shiftKey
)
return
;
e
.
preventDefault
();
this
.
next
();
break
;
}
},
keydown
:
function
(
e
)
{
this
.
suppressKeyPressRepeat
=
~
$
.
inArray
(
e
.
keyCode
,
[
40
,
38
,
9
,
13
,
27
]);
if
(
!
this
.
shown
&&
e
.
keyCode
==
40
)
{
this
.
lookup
();
}
else
{
this
.
move
(
e
);
}
},
keypress
:
function
(
e
)
{
if
(
this
.
suppressKeyPressRepeat
)
return
;
this
.
move
(
e
);
},
input
:
function
(
e
)
{
this
.
lookup
();
e
.
preventDefault
();
},
keyup
:
function
(
e
)
{
switch
(
e
.
keyCode
)
{
case
40
:
// down arrow
case
38
:
// up arrow
case
16
:
// shift
case
17
:
// ctrl
case
18
:
// alt
break
;
case
9
:
// tab
case
13
:
// enter
if
(
!
this
.
shown
)
return
;
this
.
select
();
break
;
case
27
:
// escape
if
(
!
this
.
shown
)
return
;
this
.
hide
();
break
;
}
e
.
preventDefault
();
},
focus
:
function
(
e
)
{
if
(
!
this
.
focused
)
{
this
.
focused
=
true
;
if
(
this
.
options
.
showHintOnFocus
)
{
this
.
lookup
(
''
);
}
}
},
blur
:
function
(
e
)
{
this
.
focused
=
false
;
if
(
!
this
.
mousedover
&&
this
.
shown
)
this
.
hide
();
},
click
:
function
(
e
)
{
e
.
preventDefault
();
this
.
select
();
this
.
$element
.
focus
();
this
.
hide
();
},
mouseenter
:
function
(
e
)
{
this
.
mousedover
=
true
;
this
.
$menu
.
find
(
'.active'
).
removeClass
(
'active'
);
$
(
e
.
currentTarget
).
addClass
(
'active'
);
},
mouseleave
:
function
(
e
)
{
this
.
mousedover
=
false
;
if
(
!
this
.
focused
&&
this
.
shown
)
this
.
hide
();
}
};
/* TYPEAHEAD PLUGIN DEFINITION
* =========================== */
var
old
=
$
.
fn
.
typeahead
;
$
.
fn
.
typeahead
=
function
(
option
)
{
var
arg
=
arguments
;
if
(
typeof
option
==
'string'
&&
option
==
'getActive'
)
{
return
this
.
data
(
'active'
);
}
return
this
.
each
(
function
()
{
var
$this
=
$
(
this
)
,
data
=
$this
.
data
(
'typeahead'
)
,
options
=
typeof
option
==
'object'
&&
option
;
if
(
!
data
)
$this
.
data
(
'typeahead'
,
(
data
=
new
Typeahead
(
this
,
options
)));
if
(
typeof
option
==
'string'
&&
data
[
option
])
{
if
(
arg
.
length
>
1
)
{
data
[
option
].
apply
(
data
,
Array
.
prototype
.
slice
.
call
(
arg
,
1
));
}
else
{
data
[
option
]();
}
}
});
};
$
.
fn
.
typeahead
.
defaults
=
{
source
:
[],
items
:
8
,
menu
:
'<ul class="typeahead dropdown-menu" role="listbox"></ul>'
,
item
:
'<li><a class="dropdown-item" href="#" role="option"></a></li>'
,
minLength
:
1
,
scrollHeight
:
0
,
autoSelect
:
true
,
afterSelect
:
$
.
noop
,
addItem
:
false
,
delay
:
0
,
separator
:
'category'
,
headerHtml
:
'<li class="dropdown-header"></li>'
,
headerDivider
:
'<li class="divider" role="separator"></li>'
};
$
.
fn
.
typeahead
.
Constructor
=
Typeahead
;
/* TYPEAHEAD NO CONFLICT
* =================== */
$
.
fn
.
typeahead
.
noConflict
=
function
()
{
$
.
fn
.
typeahead
=
old
;
return
this
;
};
/* TYPEAHEAD DATA-API
* ================== */
$
(
document
).
on
(
'focus.typeahead.data-api'
,
'[data-provide="typeahead"]'
,
function
(
e
)
{
var
$this
=
$
(
this
);
if
(
$this
.
data
(
'typeahead'
))
return
;
$this
.
typeahead
(
$this
.
data
());
});
}));
cps/templates/edit_book.html
View file @
cd0aeb28
{% extends "layout.html" %}
{% block body %}
{% if book %}
<script
type=
"text/javascript"
>
$
(
document
).
ready
(
function
(){
$
(
'input.typeahead'
).
typeahead
({
name
:
'accounts'
,
source
:
function
(
query
,
process
)
{
$
.
ajax
({
url
:
'{{ url_for('
get_authors_json
') }} '
,
type
:
'POST'
,
dataType
:
'JSON'
,
data
:
'query='
+
query
,
success
:
function
(
data
)
{
console
.
log
(
data
);
process
(
data
);
}
});
}
});
});
</script>
<div
class=
"col-sm-3 col-lg-3 col-xs-12"
>
<div
class=
"cover"
>
{% if book.has_cover is defined %}
...
...
@@ -21,7 +41,7 @@
<p>
{{author.name.join("
&
")}}
</p>
{% endfor %}
{% endif %}
<input
type=
"text"
class=
"form-control"
name=
"author_name"
id=
"bookAuthor
"
value=
"{{book.authors[0].name}}"
>
<input
type=
"text"
data-provide=
"typeahead"
class=
"form-control typeahead"
name=
"author_name"
id=
"bookAuthor"
autocomplete=
"off
"
value=
"{{book.authors[0].name}}"
>
</div>
<div
class=
"form-group"
>
<label
for=
"description"
>
Description
</label>
...
...
cps/templates/layout.html
View file @
cd0aeb28
...
...
@@ -18,6 +18,17 @@
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script
src=
"https://code.jquery.com/jquery.js"
></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script
src=
"{{ url_for('static', filename='js/bootstrap.min.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/bootstrap3-typeahead.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/underscore.min.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/intention.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/context.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/plugins.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/main.js') }}"
></script>
</head>
<body>
<!-- Static navbar -->
...
...
@@ -127,14 +138,5 @@
</div>
</div>
</div>
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script
src=
"https://code.jquery.com/jquery.js"
></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script
src=
"{{ url_for('static', filename='js/bootstrap.min.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/underscore.min.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/intention.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/context.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/plugins.js') }}"
></script>
<script
src=
"{{ url_for('static', filename='js/main.js') }}"
></script>
</body>
</html>
cps/web.py
View file @
cd0aeb28
...
...
@@ -17,6 +17,7 @@ from werkzeug.security import generate_password_hash, check_password_hash
from
functools
import
wraps
import
base64
from
sqlalchemy.sql
import
*
import
json
app
=
(
Flask
(
__name__
))
...
...
@@ -221,6 +222,14 @@ def get_opds_download_link(book_id, format):
suffix
=
format
)
return
response
@
app
.
route
(
"/get_authors_json"
,
methods
=
[
'GET'
,
'POST'
])
def
get_authors_json
():
if
request
.
method
==
"POST"
:
form
=
request
.
form
.
to_dict
()
entries
=
db
.
session
.
execute
(
"select name from authors where name like '
%
"
+
form
[
'query'
]
+
"
%
'"
)
return
json
.
dumps
([
dict
(
r
)
for
r
in
entries
])
@
app
.
route
(
"/"
,
defaults
=
{
'page'
:
1
})
@
app
.
route
(
'/page/<int:page>'
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment