added code to support changing noo/how_many/folders and do this with json data back and forth, update the UI, all works - only search is missing now. Lots of dead code can still be deleted
This commit is contained in:
65
files.py
65
files.py
@@ -21,11 +21,12 @@ from datetime import datetime, timedelta
|
|||||||
import pytz
|
import pytz
|
||||||
import html
|
import html
|
||||||
from flask_login import login_required, current_user
|
from flask_login import login_required, current_user
|
||||||
from states import States, PA_UserState
|
from types import SimpleNamespace
|
||||||
from query import Query
|
|
||||||
|
|
||||||
# Local Class imports
|
# Local Class imports
|
||||||
################################################################################
|
################################################################################
|
||||||
|
from states import States, PA_UserState
|
||||||
|
from query import Query
|
||||||
from job import Job, JobExtra, Joblog, NewJob, SetFELog
|
from job import Job, JobExtra, Joblog, NewJob, SetFELog
|
||||||
from path import PathType, Path, MovePathDetails
|
from path import PathType, Path, MovePathDetails
|
||||||
from person import Refimg, Person, PersonRefimgLink
|
from person import Refimg, Person, PersonRefimgLink
|
||||||
@@ -472,8 +473,7 @@ def get_dir_entries():
|
|||||||
|
|
||||||
# get content of dir_id
|
# get content of dir_id
|
||||||
stmt=( select(Entry.id).join(EntryDirLink).filter(EntryDirLink.dir_eid==dir_id) )
|
stmt=( select(Entry.id).join(EntryDirLink).filter(EntryDirLink.dir_eid==dir_id) )
|
||||||
# FIXME: what do we do with ordering anyway???
|
stmt=stmt.order_by(*order_map.get(OPT.noo) )
|
||||||
#stmt=stmt.order_by(*order_map.get(OPT.noo) )
|
|
||||||
ids=db.session.execute(stmt).scalars().all()
|
ids=db.session.execute(stmt).scalars().all()
|
||||||
entries_schema = EntrySchema(many=True)
|
entries_schema = EntrySchema(many=True)
|
||||||
entries = Entry.query.filter(Entry.id.in_(ids)).all()
|
entries = Entry.query.filter(Entry.id.in_(ids)).all()
|
||||||
@@ -485,39 +485,28 @@ def get_dir_entries():
|
|||||||
################################################################################
|
################################################################################
|
||||||
def GetQueryData( OPT ):
|
def GetQueryData( OPT ):
|
||||||
query_data={}
|
query_data={}
|
||||||
query_data['query_id']=None
|
|
||||||
query_data['entry_list']=None
|
query_data['entry_list']=None
|
||||||
|
|
||||||
if OPT.path_type == 'Search':
|
|
||||||
print ("NOT YET")
|
|
||||||
return query_data
|
|
||||||
|
|
||||||
# always get the top of the (OPT.prefix) Path's eid and keep it for OPT.folders toggling/use
|
# always get the top of the (OPT.prefix) Path's eid and keep it for OPT.folders toggling/use
|
||||||
dir_stmt=( select(Entry.id).join(Dir).join(PathDirLink).join(Path).filter(Dir.rel_path == '').filter(Path.path_prefix==OPT.prefix) )
|
dir_stmt=( select(Entry.id).join(Dir).join(PathDirLink).join(Path).
|
||||||
|
filter(Dir.rel_path == '').filter(Path.path_prefix==OPT.prefix) )
|
||||||
# this should return the 1 Dir (that we want to see the content of) - and with only 1, no need to worry about order
|
# this should return the 1 Dir (that we want to see the content of) - and with only 1, no need to worry about order
|
||||||
dir_arr=db.session.execute(dir_stmt).scalars().all()
|
dir_arr=db.session.execute(dir_stmt).scalars().all()
|
||||||
dir_id=dir_arr[0]
|
dir_id=dir_arr[0]
|
||||||
|
# used to know the parent/root (in folder view), in flat view - just ignore/safe though
|
||||||
query_data['root_eid']=dir_id
|
query_data['root_eid']=dir_id
|
||||||
|
|
||||||
if OPT.folders:
|
if OPT.folders:
|
||||||
# start folder view with only the root folder
|
# start folder view with only the root folder
|
||||||
stmt=( select(Entry.id).join(EntryDirLink).filter(EntryDirLink.dir_eid==dir_id) )
|
stmt=( select(Entry.id).join(EntryDirLink).filter(EntryDirLink.dir_eid==dir_id) )
|
||||||
query_data['entry_list']=db.session.execute(stmt).scalars().all()
|
|
||||||
else:
|
else:
|
||||||
# get every File that is in the OPT.prefix Path
|
# get every File that is in the OPT.prefix Path
|
||||||
stmt=( select(Entry.id).join(File).join(EntryDirLink).join(Dir).join(PathDirLink).join(Path).filter(Path.path_prefix == OPT.prefix) )
|
stmt=( select(Entry.id).join(File).join(EntryDirLink).join(Dir).join(PathDirLink).join(Path).
|
||||||
stmt=stmt.order_by(*order_map.get(OPT.noo) )
|
filter(Path.path_prefix == OPT.prefix) )
|
||||||
query_data['entry_list']= db.session.execute(stmt).scalars().all()
|
|
||||||
|
stmt=stmt.order_by(*order_map.get(OPT.noo) )
|
||||||
|
query_data['entry_list']=db.session.execute(stmt).scalars().all()
|
||||||
|
|
||||||
# not sure I need this in hindsight - any value at all???
|
|
||||||
# # first time we get the data q_offset is 0, current=first one, search never gets here, so search_term=''
|
|
||||||
# # FIXME: Doubt we need cwd -- I only need originals to either invalidate this list, or recreate it... need to think about that a lot more
|
|
||||||
# query = Query( path_type=OPT.path_type, noo=OPT.noo, q_offset=0, folder=OPT.folders, grouping=OPT.grouping, root=OPT.root, cwd=OPT.cwd, search_term='',
|
|
||||||
# entry_list=query_data['entry_list'], current=query_data['entry_list'][0], created=datetime.now(pytz.utc) )
|
|
||||||
# db.session.add(query)
|
|
||||||
# db.session.commit()
|
|
||||||
#
|
|
||||||
# query_data['query_id']=query.id
|
|
||||||
return query_data
|
return query_data
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
@@ -570,12 +559,24 @@ def GetEntries( OPT ):
|
|||||||
|
|
||||||
return entries
|
return entries
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# /change_file_opts -> allow sort order, how_many per page, etc. to change, and
|
||||||
|
# then send back the new query_data to update entryList
|
||||||
|
################################################################################
|
||||||
@app.route("/change_file_opts", methods=["POST"])
|
@app.route("/change_file_opts", methods=["POST"])
|
||||||
@login_required
|
@login_required
|
||||||
def change_file_opts():
|
def change_file_opts2():
|
||||||
# reset options based on form post, then redirect back to orig page (with a GET to allow back button to work)
|
data = request.get_json() # Parse JSON body
|
||||||
OPT=States( request )
|
# allow dot-notation for OPT
|
||||||
return redirect( request.referrer )
|
OPT = SimpleNamespace(**data)
|
||||||
|
if OPT.folders == 'True':
|
||||||
|
OPT.folders=True
|
||||||
|
else:
|
||||||
|
OPT.folders=False
|
||||||
|
# so create a new entryList, and handle that on the client
|
||||||
|
query_data = GetQueryData( OPT )
|
||||||
|
return make_response( jsonify( query_data=query_data ) )
|
||||||
|
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# /file_list -> show detailed file list of files from import_path(s)
|
# /file_list -> show detailed file list of files from import_path(s)
|
||||||
@@ -862,12 +863,6 @@ def newview():
|
|||||||
data = request.get_json() # Parse JSON body
|
data = request.get_json() # Parse JSON body
|
||||||
eid = data.get('eid', 0) # Extract list of ids
|
eid = data.get('eid', 0) # Extract list of ids
|
||||||
|
|
||||||
# need appropriate schema? to get FaceData with entry, lists should just be
|
|
||||||
# what we have in entryList so it can help with next/prev
|
|
||||||
|
|
||||||
# include Entry for name/path, ffl (model_used), frl (distance), Face (for w/h, etc), Person (id,tag)
|
|
||||||
#stmt=select(Entry).filter(Entry.id==eid)
|
|
||||||
|
|
||||||
stmt = (
|
stmt = (
|
||||||
select(Entry)
|
select(Entry)
|
||||||
.options(
|
.options(
|
||||||
@@ -877,8 +872,7 @@ def newview():
|
|||||||
.where(Entry.id == eid)
|
.where(Entry.id == eid)
|
||||||
)
|
)
|
||||||
|
|
||||||
print( stmt )
|
# this needs unique() because:
|
||||||
# this needs unique because:
|
|
||||||
# entry (one row for id=660)
|
# entry (one row for id=660)
|
||||||
# file (one row, since file_details is a one-to-one relationship)
|
# file (one row, since file_details is a one-to-one relationship)
|
||||||
# face (many rows, since a file can have many faces)
|
# face (many rows, since a file can have many faces)
|
||||||
@@ -886,7 +880,6 @@ def newview():
|
|||||||
# The SQL query returns a Cartesian product for the joins involving collections (like faces). For example, if your file has 3 faces,
|
# The SQL query returns a Cartesian product for the joins involving collections (like faces). For example, if your file has 3 faces,
|
||||||
# the result set will have 3 rows, each with the same entry and file data, but different face, refimg, and person data.
|
# the result set will have 3 rows, each with the same entry and file data, but different face, refimg, and person data.
|
||||||
data=db.session.execute(stmt).unique().scalars().all()
|
data=db.session.execute(stmt).unique().scalars().all()
|
||||||
print( data )
|
|
||||||
return jsonify(entries_schema.dump(data))
|
return jsonify(entries_schema.dump(data))
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
<script src="{{ url_for( 'internal', filename='js/files_transform.js')}}"></script>
|
<script src="{{ url_for( 'internal', filename='js/files_transform.js')}}"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// FIXME: used by viewer code - should probably get rid of this?
|
||||||
|
var fullscreen=false;
|
||||||
document.fake_shift=0
|
document.fake_shift=0
|
||||||
document.fake_ctrl=0
|
document.fake_ctrl=0
|
||||||
var move_paths=[]
|
var move_paths=[]
|
||||||
@@ -17,22 +19,23 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
// GLOBALS
|
// GLOBALS
|
||||||
// OPTions set via GUI, will change if we alter drop-downs, etc. in GUI
|
|
||||||
// TODO: reference these from GUI, so we can finally ditch the form to submit/change them.
|
|
||||||
// BUT -- must handle noo changing with a form/post as it requires a new ordering
|
|
||||||
|
|
||||||
// this is which eid we are viewing an image/video (when we dbl-click & then next/prev)
|
// this is which eid we are viewing an image/video (when we dbl-click & then next/prev)
|
||||||
document.viewing_eid=null;
|
document.viewing_eid=null;
|
||||||
document.viewing=null;
|
document.viewing=null;
|
||||||
|
|
||||||
var OPT={}
|
var OPT={}
|
||||||
|
OPT.noo='{{OPT.noo}}'
|
||||||
|
OPT.how_many={{OPT.how_many}}
|
||||||
|
OPT.folders="{{OPT.folders}}" === "True"
|
||||||
OPT.grouping='{{OPT.grouping}}'
|
OPT.grouping='{{OPT.grouping}}'
|
||||||
OPT.cwd='{{OPT.cwd}}'
|
OPT.cwd='{{OPT.cwd}}'
|
||||||
OPT.root_eid={{query_data.root_eid}}
|
OPT.root_eid={{query_data.root_eid}}
|
||||||
OPT.search_term='{{OPT.orig_search_term}}'
|
OPT.search_term='{{OPT.orig_search_term}}'
|
||||||
OPT.folders="{{OPT.folders}}" === "True"
|
|
||||||
OPT.howMany={{OPT.how_many}}
|
|
||||||
OPT.size={{OPT.size}}
|
OPT.size={{OPT.size}}
|
||||||
|
OPT.prefix='{{OPT.prefix}}'
|
||||||
|
OPT.default_flat_noo='{{OPT.default_flat_noo}}'
|
||||||
|
OPT.default_folder_noo='{{OPT.default_folder_noo}}'
|
||||||
|
OPT.default_search_noo='{{OPT.default_search_noo}}'
|
||||||
|
|
||||||
// this is the list of entry ids for the images for ALL matches for this query
|
// this is the list of entry ids for the images for ALL matches for this query
|
||||||
var entryList={{query_data.entry_list}}
|
var entryList={{query_data.entry_list}}
|
||||||
@@ -41,6 +44,48 @@
|
|||||||
var pageList=[]
|
var pageList=[]
|
||||||
// force pageList to set pageList for & render the first page
|
// force pageList to set pageList for & render the first page
|
||||||
getPage(1)
|
getPage(1)
|
||||||
|
|
||||||
|
function cFO() {
|
||||||
|
OPT.how_many=$('#how_many').val()
|
||||||
|
new_f=$('#folders').val()
|
||||||
|
new_f=( new_f == 'True' )
|
||||||
|
// if change to/from folders, also fix the noo menu
|
||||||
|
if( new_f != OPT.folders )
|
||||||
|
{
|
||||||
|
if( new_f )
|
||||||
|
{
|
||||||
|
$('#noo option:lt(2)').prop('disabled', true);
|
||||||
|
$('#noo').val(OPT.default_folder_noo)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$('#noo option:lt(2)').prop('disabled', false);
|
||||||
|
$('#noo').val(OPT.default_flat_noo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OPT.noo=$('#noo').val()
|
||||||
|
OPT.folders=new_f
|
||||||
|
OPT.folders=$('#folders').val()
|
||||||
|
OPT.grouping=$('#grouping').val()
|
||||||
|
OPT.size=$('#size').val()
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: '/change_file_opts',
|
||||||
|
data: JSON.stringify(OPT),
|
||||||
|
contentType: 'application/json',
|
||||||
|
success: function(resp) {
|
||||||
|
entryList=resp.query_data.entry_list
|
||||||
|
// put data back into booleans, ints, etc
|
||||||
|
OPT.folders=( OPT.folders == 'True' )
|
||||||
|
OPT.how_many=parseInt(OPT.how_many)
|
||||||
|
$('.how_many_text').html( ` ${OPT.how_many} files ` )
|
||||||
|
OPT.root_eid=parseInt(OPT.root_eid)
|
||||||
|
OPT.size=parseInt(OPT.size)
|
||||||
|
getPage(1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="files_div">
|
<div id="files_div">
|
||||||
@@ -68,13 +113,13 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
<div class="col col-auto">
|
<div class="col col-auto">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
{{CreateSelect( "noo", OPT.noo, ["Oldest", "Newest","A to Z", "Z to A"], "$('#offset').val(0)", "rounded-start py-2")|safe }}
|
{{CreateSelect( "noo", OPT.noo, ["Oldest", "Newest","A to Z", "Z to A"], "cFO(); return false", "rounded-start py-2")|safe }}
|
||||||
{{CreateSelect( "how_many", OPT.how_many|string, ["10", "25", "50", "75", "100", "150", "200", "500"])|safe }}
|
{{CreateSelect( "how_many", OPT.how_many|string, ["10", "25", "50", "75", "100", "150", "200", "500"], "cFO(); return false" )|safe }}
|
||||||
{% if OPT.folders %}
|
{% if OPT.folders %}
|
||||||
<input type="hidden" name="grouping" id="grouping" value="{{OPT.grouping}}">
|
<input type="hidden" name="grouping" id="grouping" value="{{OPT.grouping}}">
|
||||||
{{CreateFoldersSelect( OPT.folders, "rounded-end" )|safe }}
|
{{CreateFoldersSelect( OPT.folders, "cFO(); return false", "rounded-end" )|safe }}
|
||||||
{% else %}
|
{% else %}
|
||||||
{{CreateFoldersSelect( OPT.folders )|safe }}
|
{{CreateFoldersSelect( OPT.folders, "cFO(); return false" )|safe }}
|
||||||
<span class="sm-txt my-auto btn btn-outline-info disabled border-top border-bottom">grouped by:</span>
|
<span class="sm-txt my-auto btn btn-outline-info disabled border-top border-bottom">grouped by:</span>
|
||||||
{{CreateSelect( "grouping", OPT.grouping, ["None", "Day", "Week", "Month"], "OPT.grouping=$('#grouping').val();drawPageOfFigures();return false", "rounded-end")|safe }}
|
{{CreateSelect( "grouping", OPT.grouping, ["None", "Day", "Week", "Month"], "OPT.grouping=$('#grouping').val();drawPageOfFigures();return false", "rounded-end")|safe }}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -92,7 +137,7 @@
|
|||||||
<button aria-label="prev" id="prev" name="prev" class="prev sm-txt btn btn-outline-secondary disabled" onClick="prevPage()" disabled>
|
<button aria-label="prev" id="prev" name="prev" class="prev sm-txt btn btn-outline-secondary disabled" onClick="prevPage()" disabled>
|
||||||
<svg width="16" height="16" fill="currentColor"><use xlink:href="{{url_for('internal', filename='icons.svg')}}#prev"/></svg>
|
<svg width="16" height="16" fill="currentColor"><use xlink:href="{{url_for('internal', filename='icons.svg')}}#prev"/></svg>
|
||||||
</button>
|
</button>
|
||||||
<span class="sm-txt my-auto"> {{OPT.how_many}} files </span>
|
<span class="how_many_text sm-txt my-auto"> {{OPT.how_many}} files </span>
|
||||||
<button aria-label="next" id="next" name="next" class="next sm-txt btn btn-outline-secondary" onClick="nextPage()">
|
<button aria-label="next" id="next" name="next" class="next sm-txt btn btn-outline-secondary" onClick="nextPage()">
|
||||||
<svg width="16" height="16" fill="currentColor"><use xlink:href="{{url_for('internal', filename='icons.svg')}}#next"/></svg>
|
<svg width="16" height="16" fill="currentColor"><use xlink:href="{{url_for('internal', filename='icons.svg')}}#next"/></svg>
|
||||||
</button>
|
</button>
|
||||||
@@ -163,7 +208,7 @@
|
|||||||
<button aria-label="prev" id="prev" name="prev" class="prev sm-txt btn btn-outline-secondary disabled" onClick="prevPage()" disabled>
|
<button aria-label="prev" id="prev" name="prev" class="prev sm-txt btn btn-outline-secondary disabled" onClick="prevPage()" disabled>
|
||||||
<svg width="16" height="16" fill="currentColor"><use xlink:href="{{url_for('internal', filename='icons.svg')}}#prev"/></svg>
|
<svg width="16" height="16" fill="currentColor"><use xlink:href="{{url_for('internal', filename='icons.svg')}}#prev"/></svg>
|
||||||
</button>
|
</button>
|
||||||
<span class="sm-txt my-auto"> {{OPT.how_many}} files </span>
|
<span class="how_many_text sm-txt my-auto"> {{OPT.how_many}} files </span>
|
||||||
<button aria-label="next" id="next" name="next" class="next sm-txt btn btn-outline-secondary" onClick="nextPage()">
|
<button aria-label="next" id="next" name="next" class="next sm-txt btn btn-outline-secondary" onClick="nextPage()">
|
||||||
<svg width="16" height="16" fill="currentColor"><use xlink:href="{{url_for('internal', filename='icons.svg')}}#next"/></svg>
|
<svg width="16" height="16" fill="currentColor"><use xlink:href="{{url_for('internal', filename='icons.svg')}}#next"/></svg>
|
||||||
</button>
|
</button>
|
||||||
@@ -227,11 +272,11 @@
|
|||||||
function getPreviousEntry() {
|
function getPreviousEntry() {
|
||||||
var currentIndex = entryList.indexOf(document.viewing.id);
|
var currentIndex = entryList.indexOf(document.viewing.id);
|
||||||
|
|
||||||
oldPageOffset=Math.floor(currentIndex / OPT.howMany)
|
oldPageOffset=Math.floor(currentIndex / OPT.how_many)
|
||||||
if (currentIndex > 0) {
|
if (currentIndex > 0) {
|
||||||
currentIndex--;
|
currentIndex--;
|
||||||
pageOffset=Math.floor(currentIndex / OPT.howMany)
|
pageOffset=Math.floor(currentIndex / OPT.how_many)
|
||||||
currentIndex=currentIndex-(pageOffset*OPT.howMany)
|
currentIndex=currentIndex-(pageOffset*OPT.how_many)
|
||||||
// pref page, load it
|
// pref page, load it
|
||||||
if( oldPageOffset != pageOffset )
|
if( oldPageOffset != pageOffset )
|
||||||
// pref page is pageOffset+1 now
|
// pref page is pageOffset+1 now
|
||||||
@@ -244,11 +289,11 @@
|
|||||||
function getNextEntry() {
|
function getNextEntry() {
|
||||||
var currentIndex = entryList.indexOf(document.viewing.id);
|
var currentIndex = entryList.indexOf(document.viewing.id);
|
||||||
|
|
||||||
oldPageOffset=Math.floor(currentIndex / OPT.howMany)
|
oldPageOffset=Math.floor(currentIndex / OPT.how_many)
|
||||||
if (currentIndex < entryList.length - 1) {
|
if (currentIndex < entryList.length - 1) {
|
||||||
currentIndex++
|
currentIndex++
|
||||||
pageOffset=Math.floor(currentIndex / OPT.howMany)
|
pageOffset=Math.floor(currentIndex / OPT.how_many)
|
||||||
currentIndex=currentIndex-(pageOffset*OPT.howMany)
|
currentIndex=currentIndex-(pageOffset*OPT.how_many)
|
||||||
// next page, load it
|
// next page, load it
|
||||||
if( oldPageOffset != pageOffset )
|
if( oldPageOffset != pageOffset )
|
||||||
// next page is pageOffset+1 now
|
// next page is pageOffset+1 now
|
||||||
@@ -268,9 +313,9 @@
|
|||||||
|
|
||||||
function setEntryById(id) {
|
function setEntryById(id) {
|
||||||
var currentIndex = entryList.indexOf(parseInt(id));
|
var currentIndex = entryList.indexOf(parseInt(id));
|
||||||
// if we are on a different page, adjust as document.entries only has <= howMany
|
// if we are on a different page, adjust as document.entries only has <= how_many
|
||||||
pageOffset=Math.floor(currentIndex / OPT.howMany)
|
pageOffset=Math.floor(currentIndex / OPT.how_many)
|
||||||
currentIndex = currentIndex-(pageOffset*OPT.howMany)
|
currentIndex = currentIndex-(pageOffset*OPT.how_many)
|
||||||
document.viewing=document.entries[currentIndex]
|
document.viewing=document.entries[currentIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,7 +578,7 @@ $.contextMenu({
|
|||||||
return {
|
return {
|
||||||
callback: function( key, options) {
|
callback: function( key, options) {
|
||||||
if( key == "details" ) { DetailsDBox() }
|
if( key == "details" ) { DetailsDBox() }
|
||||||
if( key == "view" ) { CallViewRoute( $(this).attr('id') ) }
|
if( key == "view" ) { dblClickToViewEntry( $(this).attr('id') ) }
|
||||||
if( key == "move" ) { MoveDBox(move_paths, "{{url_for('internal', filename='icons.svg')}}") }
|
if( key == "move" ) { MoveDBox(move_paths, "{{url_for('internal', filename='icons.svg')}}") }
|
||||||
if( key == "del" ) { DelDBox('Delete') }
|
if( key == "del" ) { DelDBox('Delete') }
|
||||||
if( key == "undel") { DelDBox('Restore') }
|
if( key == "undel") { DelDBox('Restore') }
|
||||||
@@ -552,15 +597,6 @@ $.contextMenu({
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$(document).ready(function() {
|
|
||||||
if( {{OPT.offset}} == 0 )
|
|
||||||
{
|
|
||||||
$('.prev').addClass('disabled')
|
|
||||||
$('.prev').prop('disabled', true)
|
|
||||||
}
|
|
||||||
$(".dir").click( function(e) { $('#offset').val(0) ; $('#cwd').val( $(this).attr('dir') ) ; $('#main_form').submit() } )
|
|
||||||
} )
|
|
||||||
|
|
||||||
$( document ).keydown(function(event) {
|
$( document ).keydown(function(event) {
|
||||||
switch (event.key)
|
switch (event.key)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user