Merge ssh://github.com/web2py/web2py
This commit is contained in:
@@ -30,7 +30,7 @@ update:
|
||||
echo "remember that pymysql was tweaked"
|
||||
src:
|
||||
### Use semantic versioning
|
||||
echo 'Version 2.5.1-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
||||
echo 'Version 2.6.0-development+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
||||
### rm -f all junk files
|
||||
make clean
|
||||
### clean up baisc apps
|
||||
|
||||
@@ -1 +1 @@
|
||||
Version 2.5.1-stable+timestamp.2013.06.24.14.23.41
|
||||
Version 2.6.0-development+timestamp.2013.06.30.10.46.28
|
||||
|
||||
@@ -3,54 +3,62 @@
|
||||
'!langcode!': 'de',
|
||||
'!langname!': 'Deutsch',
|
||||
'"update" is an optional expression like "field1=\'newvalue\'". You cannot update or delete the results of a JOIN': '"Update" ist ein optionaler Ausdruck wie "Feld1 = \'newvalue". JOIN Ergebnisse können nicht aktualisiert oder gelöscht werden',
|
||||
'%s %%{row} deleted': '%s Zeilen gelöscht',
|
||||
'%s %%{row} updated': '%s Zeilen aktualisiert',
|
||||
'%Y-%m-%d': '%Y-%m-%d',
|
||||
'%Y-%m-%d %H:%M:%S': '%Y-%m-%d %H:%M:%S',
|
||||
'(requires internet access)': '(requires internet access)',
|
||||
'%s %%{row} deleted': '%s %%{row} Zeilen gelöscht',
|
||||
'%s %%{row} updated': '%s %%{row} Zeilen aktualisiert',
|
||||
'%Y-%m-%d': '%d.%m.%Y',
|
||||
'%Y-%m-%d %H:%M:%S': '%d.%m.%Y %H:%M:%S',
|
||||
'(requires internet access)': '(Internet Zugang wir benötigt)',
|
||||
'(requires internet access, experimental)': '(benötigt Internet Zugang)',
|
||||
'(something like "it-it")': '(so etwas wie "it-it")',
|
||||
'@markmin\x01Searching: **%s** %%{file}': 'Searching: **%s** files',
|
||||
'@markmin\x01(file **gluon/contrib/plural_rules/%s.py** is not found)': '(file **gluon/contrib/plural_rules/%s.py** is not found)',
|
||||
'@markmin\x01Searching: **%s** %%{file}': '@markmin\x01Suche: **%s** Dateien',
|
||||
'A new version of web2py is available': 'Eine neue Version von web2py ist verfügbar',
|
||||
'A new version of web2py is available: %s': 'Eine neue Version von web2py ist verfügbar: %s',
|
||||
'Abort': 'Abbrechen',
|
||||
'About': 'Über',
|
||||
'About application': 'Über die Anwendung',
|
||||
'Additional code for your application': 'Additional code for your application',
|
||||
'additional code for your application': 'zusätzlicher Code für Ihre Anwendung',
|
||||
'admin disabled because no admin password': ' admin ist deaktiviert, weil kein Admin-Passwort gesetzt ist',
|
||||
'About': 'über',
|
||||
'About application': 'über die Anwendung',
|
||||
'Additional code for your application': 'zusätzlicher Code für Ihre Anwendung',
|
||||
'admin disabled because no admin password': 'admin ist deaktiviert, weil kein Admin-Passwort gesetzt ist',
|
||||
'admin disabled because not supported on google apps engine': 'admin ist deaktiviert, es existiert dafür keine Unterstützung auf der google apps engine',
|
||||
'admin disabled because unable to access password file': 'admin ist deaktiviert, weil kein Zugriff auf die Passwortdatei besteht',
|
||||
'Admin is disabled because insecure channel': 'Appadmin ist deaktiviert, wegen der Benutzung eines unsicheren Kanals',
|
||||
'Admin is disabled because unsecure channel': 'Appadmin ist deaktiviert, wegen der Benutzung eines unsicheren Kanals',
|
||||
'Admin language': 'Admin language',
|
||||
'administrative interface': 'administrative interface',
|
||||
'Admin language': 'Admin-Sprache',
|
||||
'administrative interface': 'Administrative Schnittstelle',
|
||||
'Administrator Password:': 'Administrator Passwort:',
|
||||
'An error occured, please %s the page': 'Ein Fehler ist aufgetereten, bitte %s die Seite',
|
||||
'and rename it (required):': 'und benenne sie um (erforderlich):',
|
||||
'and rename it:': ' und benenne sie um:',
|
||||
'appadmin': 'appadmin',
|
||||
'appadmin is disabled because insecure channel': 'Appadmin ist deaktiviert, wegen der Benutzung eines unsicheren Kanals',
|
||||
'Application': 'Anwendung',
|
||||
'application "%s" uninstalled': 'Anwendung "%s" deinstalliert',
|
||||
'application compiled': 'Anwendung kompiliert',
|
||||
'application is compiled and cannot be designed': 'Die Anwendung ist kompiliert kann deswegen nicht mehr geändert werden',
|
||||
'Application name:': 'Application name:',
|
||||
'Application name:': 'Name der Applikation:',
|
||||
'are not used': 'wird nicht verwendet',
|
||||
'are not used yet': 'wird bisher nicht verwendet',
|
||||
'Are you sure you want to delete file "%s"?': 'Sind Sie sich sicher, dass Sie diese Datei löschen wollen "%s"?',
|
||||
'Are you sure you want to delete this object?': 'Are you sure you want to delete this object?',
|
||||
'Are you sure you want to delete this object?': 'Sind Sie sich sicher, dass Sie dieses Objekt löschen wollen?',
|
||||
'Are you sure you want to uninstall application "%s"': 'Sind Sie sich sicher, dass Sie diese Anwendung deinstallieren wollen "%s"',
|
||||
'Are you sure you want to uninstall application "%s"?': 'Sind Sie sich sicher, dass Sie diese Anwendung deinstallieren wollen "%s"?',
|
||||
'Are you sure you want to upgrade web2py now?': 'Sind Sie sich sicher, dass Sie web2py jetzt upgraden möchten?',
|
||||
'arguments': 'arguments',
|
||||
'at char %s': 'at char %s',
|
||||
'at line %s': 'at line %s',
|
||||
'ATTENTION: Login requires a secure (HTTPS) connection or running on localhost.': 'ACHTUNG: Die Einwahl benötigt eine sichere (HTTPS) Verbindung. Es sei denn sie läuft Lokal(localhost).',
|
||||
'ATTENTION: TESTING IS NOT THREAD SAFE SO DO NOT PERFORM MULTIPLE TESTS CONCURRENTLY.': 'ACHTUNG: Testen ist nicht threadsicher. Führen sie also nicht mehrere Tests gleichzeitig aus.',
|
||||
'ATTENTION: This is an experimental feature and it needs more testing.': 'ACHTUNG: Dies ist eine experimentelle Funktion und benötigt noch weitere Tests.',
|
||||
'ATTENTION: you cannot edit the running application!': 'ACHTUNG: Eine laufende Anwendung kann nicht editiert werden!',
|
||||
'Authentication': 'Authentifizierung',
|
||||
'Available databases and tables': 'Verfügbare Datenbanken und Tabellen',
|
||||
'Available databases and tables': 'verfügbare Datenbanken und Tabellen',
|
||||
'back': 'zurück',
|
||||
'beautify': 'beautify',
|
||||
'cache': 'Cache',
|
||||
'beautify': 'verschönern',
|
||||
'cache': 'Pufferspeicher',
|
||||
'cache, errors and sessions cleaned': 'Zwischenspeicher (cache), Fehler und Sitzungen (sessions) gelöscht',
|
||||
'call': 'call',
|
||||
'can be a git repo': 'can be a git repo',
|
||||
'call': 'Aufruf',
|
||||
'can be a git repo': 'kann ein git Repository sein',
|
||||
'Cancel': 'Cancel',
|
||||
'Cannot be empty': 'Darf nicht leer sein',
|
||||
'Cannot compile: there are errors in your app. Debug it, correct errors and try again.': 'Nicht Kompilierbar:Es sind Fehler in der Anwendung. Beseitigen Sie die Fehler und versuchen Sie es erneut.',
|
||||
'cannot create file': 'Kann Datei nicht erstellen',
|
||||
@@ -62,29 +70,31 @@
|
||||
'Check for upgrades': 'check for upgrades',
|
||||
'Check to delete': 'Markiere zum löschen',
|
||||
'Checking for upgrades...': 'Auf Updates überprüfen...',
|
||||
'Clean': 'löschen',
|
||||
'Clean': 'leeren',
|
||||
'click here for online examples': 'hier klicken für online Beispiele',
|
||||
'click here for the administrative interface': 'hier klicken für die Administrationsoberfläche ',
|
||||
'Click row to expand traceback': 'Klicke auf die Zeile für Fehlerverfolgung',
|
||||
'click to check for upgrades': 'hier klicken um nach Upgrades zu suchen',
|
||||
'Client IP': 'Client IP',
|
||||
'code': 'code',
|
||||
'collapse/expand all': 'collapse/expand all',
|
||||
'collapse/expand all': 'alles zu- bzw. aufklappen',
|
||||
'Compile': 'kompilieren',
|
||||
'compiled application removed': 'kompilierte Anwendung gelöscht',
|
||||
'Controller': 'Controller',
|
||||
'Controllers': 'Controller',
|
||||
'controllers': 'Controllers',
|
||||
'Copyright': 'Urheberrecht',
|
||||
'Count': 'Anzahl',
|
||||
'Create': 'erstellen',
|
||||
'create file with filename:': 'erzeuge Datei mit Dateinamen:',
|
||||
'create new application:': 'erzeuge neue Anwendung:',
|
||||
'Create new simple application': 'Erzeuge neue Anwendung',
|
||||
'created by': 'created by',
|
||||
'created by': 'erstellt von',
|
||||
'crontab': 'crontab',
|
||||
'Current request': 'Aktuelle Anfrage (request)',
|
||||
'Current response': 'Aktuelle Antwort (response)',
|
||||
'Current session': 'Aktuelle Sitzung (session)',
|
||||
'currently running': 'currently running',
|
||||
'currently running': 'aktuell in Betrieb',
|
||||
'currently saved or': 'des derzeit gespeicherten oder',
|
||||
'customize me!': 'pass mich an!',
|
||||
'data uploaded': 'Daten hochgeladen',
|
||||
@@ -97,23 +107,27 @@
|
||||
'DB Model': 'DB Modell',
|
||||
'Debug': 'Debug',
|
||||
'defines tables': 'definiere Tabellen',
|
||||
'Delete': 'Löschen',
|
||||
'Delete': 'löschen',
|
||||
'delete': 'löschen',
|
||||
'delete all checked': 'lösche alle markierten',
|
||||
'delete plugin': 'Plugin löschen',
|
||||
'Delete:': 'Löschen:',
|
||||
'Deploy': 'deploy',
|
||||
'Delete this file (you will be asked to confirm deletion)': 'Delete this file (you will be asked to confirm deletion)',
|
||||
'Delete:': 'löschen:',
|
||||
'Deploy': 'Installieren',
|
||||
'Deploy on Google App Engine': 'Auf Google App Engine installieren',
|
||||
'Deploy to OpenShift': 'Deploy to OpenShift',
|
||||
'Deploy to OpenShift': 'Auf OpenShift installieren',
|
||||
'Description': 'Beschreibung',
|
||||
'design': 'design',
|
||||
'DESIGN': 'design',
|
||||
'Design for': 'Design für',
|
||||
'Detailed traceback description': 'Detailed traceback description',
|
||||
'direction: ltr': 'direction: ltr',
|
||||
'Disable': 'Disable',
|
||||
'Disable': 'Deaktivieren',
|
||||
'docs': 'docs',
|
||||
'documentation': 'Dokumentation',
|
||||
'done!': 'fertig!',
|
||||
'download layouts': 'download layouts',
|
||||
'Download .w2p': 'Download .w2p',
|
||||
'download layouts': 'Layouts herunterladen',
|
||||
'download plugins': 'download plugins',
|
||||
'E-mail': 'E-mail',
|
||||
'EDIT': 'BEARBEITEN',
|
||||
@@ -128,16 +142,23 @@
|
||||
'Editing file': 'Bearbeite Datei',
|
||||
'Editing file "%s"': 'Bearbeite Datei "%s"',
|
||||
'Editing Language file': 'Sprachdatei bearbeiten',
|
||||
'Enable': 'Enable',
|
||||
'Enterprise Web Framework': 'Enterprise Web Framework',
|
||||
'Error': 'Fehler',
|
||||
'Error logs for "%(app)s"': 'Fehlerprotokoll für "%(app)s"',
|
||||
'Error snapshot': 'Error snapshot',
|
||||
'Error ticket': 'Error ticket',
|
||||
'Errors': 'Fehler',
|
||||
'escape': 'escape',
|
||||
'Exception instance attributes': 'Atribute der Ausnahmeinstanz',
|
||||
'Expand Abbreviation': 'Kürzel erweitern',
|
||||
'export as csv file': 'Exportieren als CSV-Datei',
|
||||
'exposes': 'stellt zur Verfügung',
|
||||
'exposes:': 'exposes:',
|
||||
'extends': 'erweitert',
|
||||
'failed to compile file because:': 'failed to compile file because:',
|
||||
'failed to reload module': 'neu laden des Moduls fehlgeschlagen',
|
||||
'File': 'Datei',
|
||||
'file "%(filename)s" created': 'Datei "%(filename)s" erstellt',
|
||||
'file "%(filename)s" deleted': 'Datei "%(filename)s" gelöscht',
|
||||
'file "%(filename)s" uploaded': 'Datei "%(filename)s" hochgeladen',
|
||||
@@ -148,25 +169,33 @@
|
||||
'file saved on %(time)s': 'Datei gespeichert am %(time)s',
|
||||
'file saved on %s': 'Datei gespeichert auf %s',
|
||||
'filter': 'filter',
|
||||
'Find Next': 'Find Next',
|
||||
'Find Previous': 'Find Previous',
|
||||
'First name': 'Vorname',
|
||||
'Frames': 'Frames',
|
||||
'Functions with no doctests will result in [passed] tests.': 'Funktionen ohne doctests erzeugen [passed] in Tests',
|
||||
'Get from URL:': 'Get from URL:',
|
||||
'Git Pull': 'Git Pull',
|
||||
'Git Push': 'Git Push',
|
||||
'Go to Matching Pair': 'gehe zum übereinstimmenden Paar',
|
||||
'Goto': 'Goto',
|
||||
'graph model': 'graph model',
|
||||
'Group ID': 'Gruppen ID',
|
||||
'Hello World': 'Hallo Welt',
|
||||
'Help': 'Hilfe',
|
||||
'Hide/Show Translated strings': 'Hide/Show Translated strings',
|
||||
'Home': 'Home',
|
||||
'htmledit': 'htmledit',
|
||||
'If the report above contains a ticket number it indicates a failure in executing the controller, before any attempt to execute the doctests. This is usually due to an indentation error or an error outside function code.\nA green title indicates that all tests (if defined) passed. In this case test results are not shown.': 'Falls der obere Test eine Fehler-Ticketnummer enthält deutet das auf einen Fehler in der Ausführung des Controllers hin, noch bevor der Doctest ausgeführt werden konnte. Gewöhnlich führen fehlerhafte Einrückungen oder fehlerhafter Code ausserhalb der Funktion zu solchen Fehlern. Ein grüner Titel deutet darauf hin, dass alle Test(wenn sie vorhanden sind) erfolgreich durchlaufen wurden. In diesem Fall werden die Testresultate nicht angezeigt.',
|
||||
'If the report above contains a ticket number it indicates a failure in executing the controller, before any attempt to execute the doctests. This is usually due to an indentation error or an error outside function code.\nA green title indicates that all tests (if defined) passed. In this case test results are not shown.': 'Falls der obere Test eine Fehler-Ticketnummer enthält deutet das auf einen Fehler in der Ausführung des Controllers hin, noch bevor der Doctest ausgeführt werden konnte. Gewöhnlich Führen fehlerhafte Einrückungen oder fehlerhafter Code ausserhalb der Funktion zu solchen Fehlern. Ein grüner Titel deutet darauf hin, dass alle Test(wenn sie vorhanden sind) erfolgreich durchlaufen wurden. In diesem Fall werden die Testresultate nicht angezeigt.',
|
||||
'If you answer "yes", be patient, it may take a while to download': '',
|
||||
'If you answer yes, be patient, it may take a while to download': 'If you answer yes, be patient, it may take a while to download',
|
||||
'Import/Export': 'Importieren/Exportieren',
|
||||
'includes': 'Einfügen',
|
||||
'Index': 'Index',
|
||||
'index': 'index',
|
||||
'insert new': 'neu einfügen',
|
||||
'insert new %s': 'neu einfügen %s',
|
||||
'insert new': 'neu Einfügen',
|
||||
'insert new %s': 'neu Einfügen %s',
|
||||
'inspect attributes': 'inspect attributes',
|
||||
'Install': 'installieren',
|
||||
'Installed applications': 'Installierte Anwendungen',
|
||||
'internal error': 'interner Fehler',
|
||||
@@ -175,9 +204,10 @@
|
||||
'Invalid email': 'Ungültige Email',
|
||||
'invalid password': 'Ungültiges Passwort',
|
||||
'Invalid Query': 'Ungültige Abfrage',
|
||||
'invalid request': 'ungültige Anfrage',
|
||||
'invalid ticket': 'ungültiges Ticket',
|
||||
'invalid request': 'Ungültige Anfrage',
|
||||
'invalid ticket': 'Ungültiges Ticket',
|
||||
'Key bindings': 'Tastenbelegungen',
|
||||
'Key bindings for ZenCoding Plugin': 'Key bindings for ZenCoding Plugin',
|
||||
'Key bindings for ZenConding Plugin': 'Tastenbelegungen für das ZenConding Plugin',
|
||||
'language file "%(filename)s" created/updated': 'Sprachdatei "%(filename)s" erstellt/aktualisiert',
|
||||
'Language files (static strings) updated': 'Sprachdatei (statisch Strings) aktualisiert',
|
||||
@@ -189,6 +219,7 @@
|
||||
'Layout': 'Layout',
|
||||
'License for': 'Lizenz für',
|
||||
'loading...': 'lade...',
|
||||
'locals': 'locals',
|
||||
'located in the file': 'located in Datei',
|
||||
'Login': 'Anmelden',
|
||||
'login': 'anmelden',
|
||||
@@ -196,7 +227,8 @@
|
||||
'Logout': 'abmelden',
|
||||
'Lost Password': 'Passwort vergessen',
|
||||
'lost password?': 'Passwort vergessen?',
|
||||
'Main Menu': 'Menú principal',
|
||||
'Main Menu': 'Menü principal',
|
||||
'Manage': 'Verwalten',
|
||||
'Match Pair': 'Paare finden',
|
||||
'Menu Model': 'Menü Modell',
|
||||
'merge': 'verbinden',
|
||||
@@ -207,22 +239,28 @@
|
||||
'modules': 'Module',
|
||||
'Name': 'Name',
|
||||
'new application "%s" created': 'neue Anwendung "%s" erzeugt',
|
||||
'New application wizard': 'New application wizard',
|
||||
'New application wizard': 'Neue Anwendung per Assistent',
|
||||
'new plugin installed': 'new plugin installed',
|
||||
'New Record': 'Neuer Datensatz',
|
||||
'new record inserted': 'neuer Datensatz eingefügt',
|
||||
'New simple application': 'New simple application',
|
||||
'New simple application': 'Neue einfache Anwendung',
|
||||
'next 100 rows': 'nächsten 100 Zeilen',
|
||||
'Next Edit Point': 'nächster Bearbeitungsschritt',
|
||||
'NO': 'NEIN',
|
||||
'No databases in this application': 'Keine Datenbank in dieser Anwendung',
|
||||
'No ticket_storage.txt found under /private folder': 'No ticket_storage.txt found under /private folder',
|
||||
'online designer': 'online designer',
|
||||
'or alternatively': 'or alternatively',
|
||||
'Or Get from URL:': 'oder hole es von folgender URL:',
|
||||
'or import from csv file': 'oder importieren von cvs Datei',
|
||||
'or provide app url:': 'oder geben Sie eine Anwendungs-URL an:',
|
||||
'or provide application url:': 'oder geben Sie eine Anwendungs-URL an:',
|
||||
'Origin': 'Herkunft',
|
||||
'Original/Translation': 'Original/Übersetzung',
|
||||
'Original/Translation': 'Original/übersetzung',
|
||||
'Overwrite installed app': 'installierte Anwendungen überschreiben',
|
||||
'Pack all': 'verpacke alles',
|
||||
'Pack compiled': 'Verpacke kompiliert',
|
||||
'Pack custom': 'Verpacke individuell',
|
||||
'pack plugin': 'Plugin verpacken',
|
||||
'Password': 'Passwort',
|
||||
'Peeking at file': 'Dateiansicht',
|
||||
@@ -230,9 +268,13 @@
|
||||
'Plugin "%s" in application': 'Plugin "%s" in Anwendung',
|
||||
'plugins': 'plugins',
|
||||
'Plugins': 'Plugins',
|
||||
'Plural-Forms:': 'Plural-Forms:',
|
||||
'Powered by': 'Unterstützt von',
|
||||
'previous 100 rows': 'vorherige 100 zeilen',
|
||||
'Previous Edit Point': 'vorheriger Bearbeitungsschritt',
|
||||
'Private files': 'Private files',
|
||||
'private files': 'private files',
|
||||
'Project Progress': 'Projekt Fortschritt',
|
||||
'Query:': 'Abfrage:',
|
||||
'record': 'Datensatz',
|
||||
'record does not exist': 'Datensatz existiert nicht',
|
||||
@@ -241,26 +283,39 @@
|
||||
'register': 'Registrierung',
|
||||
'Register': 'registrieren',
|
||||
'Registration key': 'Registrierungsschlüssel',
|
||||
'Reload routes': 'Reload routes',
|
||||
'Remove compiled': 'kompilat gelöscht',
|
||||
'reload': 'Neu laden',
|
||||
'Reload routes': 'Routen neu laden',
|
||||
'Remove compiled': 'Bytecode löschen',
|
||||
'Replace': 'Replace',
|
||||
'Replace All': 'Replace All',
|
||||
'request': 'request',
|
||||
'Reset Password key': 'Passwortschlüssel zurücksetzen',
|
||||
'Resolve Conflict file': 'bereinige Konflikt-Datei',
|
||||
'response': 'Antwort',
|
||||
'restore': 'wiederherstellen',
|
||||
'revert': 'zurückkehren',
|
||||
'Role': 'Rolle',
|
||||
'Rows in table': 'Zeilen in Tabelle',
|
||||
'Rows selected': 'Zeilen ausgewählt',
|
||||
'Running on %s': 'Running on %s',
|
||||
'rules are not defined': 'rules are not defined',
|
||||
"Run tests in this file (to run all files, you may also use the button labelled 'test')": "Run tests in this file (to run all files, you may also use the button labelled 'test')",
|
||||
'Running on %s': 'läuft auf %s',
|
||||
'Save': 'Save',
|
||||
'save': 'sichern',
|
||||
'Save file:': 'Save file:',
|
||||
'Save via Ajax': 'via Ajax sichern',
|
||||
'Saved file hash:': 'Gespeicherter Datei-Hash:',
|
||||
'Select Files to Package': 'Dateien zum Paketieren wählen',
|
||||
'selected': 'ausgewählt(e)',
|
||||
'session expired': 'Sitzung Abgelaufen',
|
||||
'session': 'Sitzung',
|
||||
'session expired': 'Sitzung abgelaufen',
|
||||
'shell': 'shell',
|
||||
'Site': 'Seite',
|
||||
'some files could not be removed': 'einige Dateien konnten nicht gelöscht werden',
|
||||
'Start wizard': 'start wizard',
|
||||
'Start searching': 'Start searching',
|
||||
'Start wizard': 'Assistent starten',
|
||||
'state': 'Status',
|
||||
'Static': 'Static',
|
||||
'static': 'statische Dateien',
|
||||
'Static files': 'statische Dateien',
|
||||
'Stylesheet': 'Stylesheet',
|
||||
@@ -283,27 +338,35 @@
|
||||
'The data representation, define database tables and sets': 'The data representation, define database tables and sets',
|
||||
'The output of the file is a dictionary that was rendered by the view': 'The output of the file is a dictionary that was rendered by the view',
|
||||
'The presentations layer, views are also known as templates': 'The presentations layer, views are also known as templates',
|
||||
'the presentations layer, views are also known as templates': 'Die Präsentationsschicht, Views sind auch bekannt als Vorlagen/Templates',
|
||||
'the presentations layer, views are also known as templates': 'Die präsentationsschicht, Views sind auch bekannt als Vorlagen/Templates',
|
||||
'There are no controllers': 'Keine Controller vorhanden',
|
||||
'There are no models': 'Keine Modelle vorhanden',
|
||||
'There are no modules': 'Keine Module vorhanden',
|
||||
'There are no plugins': 'There are no plugins',
|
||||
'There are no plugins': 'Keine Plugins vorhanden',
|
||||
'There are no private files': 'There are no private files',
|
||||
'There are no static files': 'Keine statischen Dateien vorhanden',
|
||||
'There are no translators, only default language is supported': 'Keine Übersetzungen vorhanden, nur die voreingestellte Sprache wird unterstützt',
|
||||
'There are no translators, only default language is supported': 'Keine übersetzungen vorhanden, nur die voreingestellte Sprache wird Unterstützt',
|
||||
'There are no views': 'Keine Views vorhanden',
|
||||
'These files are served without processing, your images go here': 'These files are served without processing, your images go here',
|
||||
'These files are not served, they are only available from within your app': 'These files are not served, they are only available from within your app',
|
||||
'These files are served without processing, your images go here': 'Diese Dateien werden ohne Verarbeitung ausgeliefert. Beispielsweise Bilder kommen hier hin.',
|
||||
'these files are served without processing, your images go here': 'Diese Dateien werden ohne Verarbeitung ausgeliefert. Beispielsweise Bilder kommen hier hin.',
|
||||
'This is a copy of the scaffolding application': 'Dies ist eine Kopie einer Grundgerüst-Anwendung',
|
||||
'This is the %(filename)s template': 'Dies ist das Template %(filename)s',
|
||||
'Ticket': 'Ticket',
|
||||
'Timestamp': 'Timestamp',
|
||||
'Ticket ID': 'Ticket ID',
|
||||
'Timestamp': 'Zeitstempel',
|
||||
'TM': 'TM',
|
||||
'to previous version.': 'zu einer früheren Version.',
|
||||
'To create a plugin, name a file/folder plugin_[name]': 'Um ein Plugin zu erstellen benennen Sie eine(n) Datei/Ordner plugin_[Name]',
|
||||
'translation strings for the application': 'Übersetzungs-Strings für die Anwendung',
|
||||
'Translation strings for the application': 'Translation strings for the application',
|
||||
'toggle breakpoint': 'toggle breakpoint',
|
||||
'Toggle Fullscreen': 'Toggle Fullscreen',
|
||||
'Traceback': 'Traceback',
|
||||
'translation strings for the application': 'übersetzungs-Strings für die Anwendung',
|
||||
'Translation strings for the application': 'übersetzungs-Strings für die Anwendung',
|
||||
'try': 'versuche',
|
||||
'try something like': 'versuche so etwas wie',
|
||||
'Try the mobile interface': 'Try the mobile interface',
|
||||
'try view': 'try view',
|
||||
'Unable to check for upgrades': 'überprüfen von Upgrades nicht möglich',
|
||||
'unable to create application "%s"': 'erzeugen von Anwendung "%s" nicht möglich',
|
||||
'unable to delete file "%(filename)s"': 'löschen von Datein "%(filename)s" nicht möglich',
|
||||
@@ -311,37 +374,40 @@
|
||||
'Unable to download app': 'herunterladen der Anwendung nicht möglich',
|
||||
'unable to parse csv file': 'analysieren der cvs Datei nicht möglich',
|
||||
'unable to uninstall "%s"': 'deinstallieren von "%s" nicht möglich',
|
||||
'uncheck all': 'alles demarkieren',
|
||||
'uncheck all': 'Selektionen entfernen',
|
||||
'Uninstall': 'deinstallieren',
|
||||
'update': 'aktualisieren',
|
||||
'update all languages': 'aktualisiere alle Sprachen',
|
||||
'Update:': 'Aktualisiere:',
|
||||
'upgrade web2py now': 'jetzt web2py upgraden',
|
||||
'upload': 'upload',
|
||||
'Upload': 'Upload',
|
||||
'Upload & install packed application': 'Verpackte Anwendung hochladen und installieren',
|
||||
'Upload a package:': 'Upload a package:',
|
||||
'Upload and install packed application': 'Upload and install packed application',
|
||||
'Upload a package:': 'Ein Packet hochladen:',
|
||||
'Upload and install packed application': 'Verpackte Anwendung hochladen und installieren',
|
||||
'upload application:': 'lade Anwendung hoch:',
|
||||
'Upload existing application': 'lade existierende Anwendung hoch',
|
||||
'upload file:': 'lade Datei hoch:',
|
||||
'upload plugin file:': 'Plugin-Datei hochladen:',
|
||||
'Use (...)&(...) for AND, (...)|(...) for OR, and ~(...) for NOT to build more complex queries.': 'Benutze (...)&(...) für AND, (...)|(...) für OR, und ~(...) für NOT, um komplexe Abfragen zu erstellen.',
|
||||
'Use an url:': 'Use an url:',
|
||||
'user': 'user',
|
||||
'Use an url:': 'Verwende URL:',
|
||||
'user': 'Nutzer',
|
||||
'User ID': 'Benutzer ID',
|
||||
'variables': 'variables',
|
||||
'variables': 'Variablen',
|
||||
'Version': 'Version',
|
||||
'Version %s.%s.%s (%s) %s': 'Version %s.%s.%s (%s) %s',
|
||||
'versioning': 'Versionierung',
|
||||
'View': 'View',
|
||||
'view': 'View',
|
||||
'Views': 'Views',
|
||||
'views': 'Views',
|
||||
'Versioning': 'Versionierung',
|
||||
'View': 'Ansicht',
|
||||
'view': 'Ansicht',
|
||||
'Views': 'Ansichten',
|
||||
'views': 'Ansichten',
|
||||
'Web Framework': 'Web Framework',
|
||||
'web2py is up to date': 'web2py ist auf dem neuesten Stand',
|
||||
'web2py Recent Tweets': 'neuste Tweets von web2py',
|
||||
'Welcome %s': 'Willkommen %s',
|
||||
'Welcome to web2py': 'Willkommen zu web2py',
|
||||
'Which called the function': 'Which called the function',
|
||||
'Which called the function': 'welche die Funktion aufrief',
|
||||
'Wrap with Abbreviation': 'mit Kürzel einhüllen',
|
||||
'xml': 'xml',
|
||||
'YES': 'JA',
|
||||
|
||||
@@ -1,242 +1,653 @@
|
||||
function popup(url) {
|
||||
newwindow=window.open(url,'name','height=400,width=600');
|
||||
if (window.focus) newwindow.focus();
|
||||
return false;
|
||||
}
|
||||
function collapse(id) { jQuery('#'+id).slideToggle(); }
|
||||
function fade(id,value) { if(value>0) jQuery('#'+id).hide().fadeIn('slow'); else jQuery('#'+id).show().fadeOut('slow'); }
|
||||
function ajax(u,s,t) {
|
||||
query = '';
|
||||
if (typeof s == "string") {
|
||||
d = jQuery(s).serialize();
|
||||
if(d){ query = d; }
|
||||
} else {
|
||||
(function ($, undefined) {
|
||||
/*
|
||||
* Unobtrusive scripting adapter for jQuery, largely taken from
|
||||
* the wonderful https://github.com/rails/jquery-ujs
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
*
|
||||
*/
|
||||
|
||||
String.prototype.reverse = function () {
|
||||
return this.split('').reverse().join('');
|
||||
};
|
||||
var web2py;
|
||||
|
||||
$.web2py = web2py = {
|
||||
|
||||
popup: function (url) {
|
||||
newwindow = window.open(url, 'name', 'height=400,width=600');
|
||||
if(window.focus) newwindow.focus();
|
||||
return false;
|
||||
},
|
||||
collapse: function (id) {
|
||||
$('#' + id).slideToggle();
|
||||
},
|
||||
fade: function (id, value) {
|
||||
if(value > 0) $('#' + id).hide().fadeIn('slow');
|
||||
else $('#' + id).show().fadeOut('slow');
|
||||
},
|
||||
ajax: function (u, s, t) {
|
||||
query = '';
|
||||
if(typeof s == "string") {
|
||||
d = $(s).serialize();
|
||||
if(d) {
|
||||
query = d;
|
||||
}
|
||||
} else {
|
||||
pcs = [];
|
||||
if (s != null && s != undefined) for(i=0; i<s.length; i++) {
|
||||
q = jQuery("[name="+s[i]+"]").serialize();
|
||||
if(q){pcs.push(q);}
|
||||
if(s != null && s != undefined) for(i = 0; i < s.length; i++) {
|
||||
q = $("[name=" + s[i] + "]").serialize();
|
||||
if(q) {
|
||||
pcs.push(q);
|
||||
}
|
||||
}
|
||||
if(pcs.length > 0) {
|
||||
query = pcs.join("&");
|
||||
}
|
||||
if (pcs.length>0){query = pcs.join("&");}
|
||||
}
|
||||
jQuery.ajax({type: "POST", url: u, data: query, success: function(msg) { if(t) { if(t==':eval') eval(msg); else if(typeof t=='string') jQuery("#"+t).html(msg); else t(msg); } } });
|
||||
}
|
||||
|
||||
String.prototype.reverse = function () { return this.split('').reverse().join('');};
|
||||
function web2py_ajax_fields(target) {
|
||||
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
||||
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
||||
jQuery("input.date",target).each(function() {Calendar.setup({inputField:this, ifFormat:date_format, showsTime:false });});
|
||||
jQuery("input.datetime",target).each(function() {Calendar.setup({inputField:this, ifFormat:datetime_format, showsTime: true, timeFormat: "24" });});
|
||||
jQuery("input.time",target).each(function(){jQuery(this).timeEntry();});
|
||||
|
||||
};
|
||||
|
||||
function web2py_ajax_init(target) {
|
||||
jQuery('.hidden', target).hide();
|
||||
jQuery('.error', target).hide().slideDown('slow');
|
||||
web2py_ajax_fields(target);
|
||||
web2py_show_if(target);
|
||||
};
|
||||
|
||||
function web2py_event_handlers() {
|
||||
var doc = jQuery(document)
|
||||
doc.on('click', '.flash', function(e){var t=jQuery(this); if(t.css('top')=='0px') t.slideUp('slow'); else t.fadeOut(); e.preventDefault();});
|
||||
doc.on('keyup', 'input.integer', function(){this.value=this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g,'').reverse();});
|
||||
doc.on('keyup', 'input.double, input.decimal', function(){this.value=this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g,'').reverse();});
|
||||
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
|
||||
doc.on('click', "input[type='checkbox'].delete", function(){if(this.checked) if(!confirm(confirm_message)) this.checked=false;});
|
||||
|
||||
doc.ajaxSuccess(function(e, xhr) {
|
||||
var redirect=xhr.getResponseHeader('web2py-redirect-location');
|
||||
var command=xhr.getResponseHeader('web2py-component-command');
|
||||
var flash=xhr.getResponseHeader('web2py-component-flash');
|
||||
if (redirect !== null) {
|
||||
window.location = redirect;
|
||||
};
|
||||
if(command !== null){
|
||||
eval(decodeURIComponent(command));
|
||||
}
|
||||
if(flash) {
|
||||
jQuery('.flash')
|
||||
.html(decodeURIComponent(flash))
|
||||
.append('<span id="closeflash">×</span>')
|
||||
.slideDown();
|
||||
}
|
||||
});
|
||||
|
||||
doc.ajaxError(function(e, xhr, settings, exception) {
|
||||
doc.off('click', '.flash')
|
||||
switch(xhr.status){
|
||||
case 500:
|
||||
$('.flash').html(ajax_error_500).slideDown();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
jQuery(function() {
|
||||
var flash = jQuery('.flash');
|
||||
flash.hide();
|
||||
if(flash.html()) flash.append('<span id="closeflash">×</span>').slideDown();
|
||||
web2py_ajax_init(document);
|
||||
web2py_event_handlers();
|
||||
});
|
||||
|
||||
function web2py_trap_form(action,target) {
|
||||
jQuery('#'+target+' form').each(function(i){
|
||||
var form=jQuery(this);
|
||||
if(!form.hasClass('no_trap'))
|
||||
form.submit(function(e){
|
||||
jQuery('.flash').hide().html('');
|
||||
web2py_ajax_page('post',action,form.serialize(),target);
|
||||
e.preventDefault();
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: u,
|
||||
data: query,
|
||||
success: function (msg) {
|
||||
if(t) {
|
||||
if(t == ':eval') eval(msg);
|
||||
else if(typeof t == 'string') $("#" + t).html(msg);
|
||||
else t(msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function web2py_trap_link(target) {
|
||||
jQuery('#'+target+' a.w2p_trap').each(function(i){
|
||||
var link=jQuery(this);
|
||||
link.click(function(e) {
|
||||
jQuery('.flash').hide().html('');
|
||||
web2py_ajax_page('get',link.attr('href'),[],target);
|
||||
e.preventDefault();
|
||||
});
|
||||
},
|
||||
ajax_fields: function (target) {
|
||||
/*this attaches something to a newly loaded fragment/page
|
||||
* Ideally all events should be bound to the document, so we can avoid calling
|
||||
* this over and over... all will be bound to the document
|
||||
*/
|
||||
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
||||
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
||||
$("input.date", target).each(function () {
|
||||
Calendar.setup({
|
||||
inputField: this,
|
||||
ifFormat: date_format,
|
||||
showsTime: false
|
||||
});
|
||||
}
|
||||
});
|
||||
$("input.datetime", target).each(function () {
|
||||
Calendar.setup({
|
||||
inputField: this,
|
||||
ifFormat: datetime_format,
|
||||
showsTime: true,
|
||||
timeFormat: "24"
|
||||
});
|
||||
});
|
||||
$("input.time", target).each(function () {
|
||||
$(this).timeEntry();
|
||||
});
|
||||
/*adds btn class to buttons*/
|
||||
$('button', target).addClass('btn');
|
||||
$('form input[type="submit"], form input[type="button"]', target).addClass('btn');
|
||||
/*no more inline javascript for PasswordWidget*/
|
||||
$('input[type=password][data-w2p_entropy]', target).each(function () {
|
||||
web2py.validate_entropy($(this));
|
||||
});
|
||||
/*no more inline javascript for ListWidget*/
|
||||
$('ul.w2p_list', target).each(function () {
|
||||
function pe(ul, e) {
|
||||
var new_line = ml(ul);
|
||||
rel(ul);
|
||||
if($(e.target).parent().is(':visible')) {
|
||||
//make sure we didn't delete the element before we insert after
|
||||
new_line.insertAfter($(e.target).parent());
|
||||
} else {
|
||||
//the line we clicked on was deleted, just add to end of list
|
||||
new_line.appendTo(ul);
|
||||
}
|
||||
new_line.find(":text").focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
function web2py_ajax_page(method, action, data, target) {
|
||||
jQuery.ajax({'type':method, 'url':action, 'data':data,
|
||||
'beforeSend':function(xhr) {
|
||||
xhr.setRequestHeader('web2py-component-location', document.location);
|
||||
xhr.setRequestHeader('web2py-component-element', target);},
|
||||
'complete':function(xhr,text){
|
||||
var html=xhr.responseText;
|
||||
var content=xhr.getResponseHeader('web2py-component-content');
|
||||
var t = jQuery('#'+target);
|
||||
if(content=='prepend') t.prepend(html);
|
||||
else if(content=='append') t.append(html);
|
||||
else if(content!='hide') t.html(html);
|
||||
web2py_trap_form(action,target);
|
||||
web2py_trap_link(target);
|
||||
web2py_ajax_init('#'+target);
|
||||
}
|
||||
});
|
||||
}
|
||||
function rl(ul, e) {
|
||||
if($(ul).children().length > 1) {
|
||||
//only remove if we have more than 1 item so the list is never empty
|
||||
$(e.target).parent().remove();
|
||||
}
|
||||
}
|
||||
|
||||
function web2py_component(action, target, timeout, times){
|
||||
jQuery(function(){
|
||||
var jelement = jQuery("#" + target);
|
||||
var element = jelement.get(0);
|
||||
var statement = "jQuery('#" + target + "').get(0).reload();";
|
||||
jelement.reload = function (){
|
||||
// Continue if times is Infinity or
|
||||
// the times limit is not reached
|
||||
if (element.reload_check()){
|
||||
web2py_ajax_page('get', action, null, target);} }; // reload
|
||||
// Method to check timing limit
|
||||
element.reload_check = function (){
|
||||
if (jelement.hasClass('w2p_component_stop')) {clearInterval(this.timing);return false;}
|
||||
if (this.reload_counter == Infinity){return true;}
|
||||
else {
|
||||
if (!isNaN(this.reload_counter)){
|
||||
this.reload_counter -= 1;
|
||||
if (this.reload_counter < 0){
|
||||
if (!this.run_once){
|
||||
clearInterval(this.timing);
|
||||
return false;
|
||||
}
|
||||
function ml(ul) {
|
||||
var line = $(ul).find("li:first").clone(true);
|
||||
line.find(':text').val('');
|
||||
return line;
|
||||
}
|
||||
|
||||
function rel(ul) {
|
||||
$(ul).find("li").each(function () {
|
||||
var trimmed = $.trim($(this.firstChild).val());
|
||||
if(trimmed == '') $(this).remove();
|
||||
else $(this.firstChild).val(trimmed);
|
||||
});
|
||||
}
|
||||
var ul = this;
|
||||
$(ul).find(":text").after('<a href="#">+</a> <a href="#">-</a>').keypress(function (e) {
|
||||
return(e.which == 13) ? pe(ul, e) : true;
|
||||
}).next().click(function (e) {
|
||||
pe(ul, e);
|
||||
e.preventDefault();
|
||||
}).next().click(function (e) {
|
||||
rl(ul, e);
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
},
|
||||
ajax_init: function (target) {
|
||||
$('.hidden', target).hide();
|
||||
web2py.manage_errors(target);
|
||||
web2py.ajax_fields(target);
|
||||
web2py.show_if_handler(target);
|
||||
web2py.component_handler(target);
|
||||
},
|
||||
//manage errors in forms
|
||||
manage_errors: function(target) {
|
||||
$('.error', target).hide().slideDown('slow');
|
||||
//$('.error', target).hide().fadeIn('slow');
|
||||
},
|
||||
event_handlers: function () {
|
||||
/* This is called once for page
|
||||
* Ideally it should bound all the things that are needed
|
||||
*/
|
||||
var doc = $(document);
|
||||
doc.on('click', '.flash', function (e) {
|
||||
var t = $(this);
|
||||
if(t.css('top') == '0px') t.slideUp('slow');
|
||||
else t.fadeOut();
|
||||
//if I want to display a clickable something
|
||||
//inside flash, I should not be prevented to follow it
|
||||
//e.preventDefault();
|
||||
});
|
||||
doc.on('keyup', 'input.integer', function () {
|
||||
this.value = this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g, '').reverse();
|
||||
});
|
||||
doc.on('keyup', 'input.double, input.decimal', function () {
|
||||
this.value = this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g, '').reverse();
|
||||
});
|
||||
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
|
||||
doc.on('click', "input[type='checkbox'].delete", function () {
|
||||
if(this.checked) if(!web2py.confirm(confirm_message)) this.checked = false;
|
||||
});
|
||||
|
||||
doc.ajaxSuccess(function (e, xhr) {
|
||||
var redirect = xhr.getResponseHeader('web2py-redirect-location');
|
||||
var command = xhr.getResponseHeader('web2py-component-command');
|
||||
var flash = xhr.getResponseHeader('web2py-component-flash');
|
||||
if(redirect !== null) {
|
||||
window.location = redirect;
|
||||
};
|
||||
if(command !== null) {
|
||||
eval(decodeURIComponent(command));
|
||||
}
|
||||
if(flash) {
|
||||
web2py.flash(decodeURIComponent(flash))
|
||||
}
|
||||
});
|
||||
|
||||
doc.ajaxError(function (e, xhr, settings, exception) {
|
||||
//personally I don't like it.
|
||||
//if there's an error it it flashed and can be removed
|
||||
//as any other message
|
||||
//doc.off('click', '.flash')
|
||||
switch(xhr.status) {
|
||||
case 500:
|
||||
web2py.flash(ajax_error_500);
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
trap_form: function (action, target) {
|
||||
$('#' + target + ' form').each(function (i) {
|
||||
var form = $(this);
|
||||
form.attr('data-w2p_target', target);
|
||||
if(!form.hasClass('no_trap')) {
|
||||
//should be there by default ?
|
||||
form.find('input[type=submit]').attr('data-w2p_disable_with', 'Working...');
|
||||
form.submit(function (e) {
|
||||
web2py.hide_flash();
|
||||
web2py.ajax_page('post', action, form.serialize(), target, form);
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
trap_link: function (target) {
|
||||
$('#' + target + ' a.w2p_trap').each(function (i) {
|
||||
var link = $(this);
|
||||
link.click(function (e) {
|
||||
web2py.hide_flash();
|
||||
web2py.ajax_page('get', link.attr('href'), [], target);
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
},
|
||||
ajax_page: function (method, action, data, target, element) {
|
||||
//element is a new parameter, but should be put be put in front
|
||||
if(element == undefined) element = $(document);
|
||||
if(web2py.fire(element, 'ajax:before')) { //test a usecase, should stop here if returns false
|
||||
$.ajax({
|
||||
'type': method,
|
||||
'url': action,
|
||||
'data': data,
|
||||
'beforeSend': function (xhr, settings) {
|
||||
//added
|
||||
xhr.setRequestHeader('web2py-component-location', document.location);
|
||||
xhr.setRequestHeader('web2py-component-element', target);
|
||||
return web2py.fire(element, 'ajax:beforeSend', [xhr, settings]); //test a usecase, should stop here if returns false
|
||||
},
|
||||
//added
|
||||
'success': function (data, status, xhr) {
|
||||
//bummer for form submissions....the element is not there after complete
|
||||
//because it gets replaced by the new response....
|
||||
element.trigger('ajax:success', [data, status, xhr]);
|
||||
},
|
||||
//added
|
||||
'error': function (xhr, status, error) {
|
||||
//bummer for form submissions....in addition to the element being not there after
|
||||
//complete because it gets replaced by the new response, standard form
|
||||
//handling just returns the same status code for good and bad
|
||||
//form submissions (i.e. that triggered a validator error)
|
||||
element.trigger('ajax:error', [xhr, status, error]);
|
||||
},
|
||||
'complete': function (xhr, status) {
|
||||
element.trigger('ajax:complete', [xhr, status]);
|
||||
var html = xhr.responseText;
|
||||
var content = xhr.getResponseHeader('web2py-component-content');
|
||||
var t = $('#' + target);
|
||||
if(content == 'prepend') t.prepend(html);
|
||||
else if(content == 'append') t.append(html);
|
||||
else if(content != 'hide') t.html(html);
|
||||
web2py.trap_form(action, target);
|
||||
web2py.trap_link(target);
|
||||
web2py.ajax_init('#' + target);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
component: function (action, target, timeout, times, el) {
|
||||
//element is a new parameter, but should be put in front
|
||||
$(function () {
|
||||
var jelement = $("#" + target);
|
||||
var element = jelement.get(0);
|
||||
var statement = "jQuery('#" + target + "').get(0).reload();";
|
||||
element.reload = function () {
|
||||
// Continue if times is Infinity or
|
||||
// the times limit is not reached
|
||||
if(element.reload_check()) {
|
||||
web2py.ajax_page('get', action, null, target, el);
|
||||
}
|
||||
}; // reload
|
||||
// Method to check timing limit
|
||||
element.reload_check = function () {
|
||||
if(jelement.hasClass('w2p_component_stop')) {
|
||||
clearInterval(this.timing);
|
||||
return false;
|
||||
}
|
||||
if(this.reload_counter == Infinity) {
|
||||
return true;
|
||||
} else {
|
||||
if(!isNaN(this.reload_counter)) {
|
||||
this.reload_counter -= 1;
|
||||
if(this.reload_counter < 0) {
|
||||
if(!this.run_once) {
|
||||
clearInterval(this.timing);
|
||||
return false;
|
||||
}
|
||||
else{return true;}
|
||||
} }
|
||||
return false;}; // reload check
|
||||
if (!isNaN(timeout)){
|
||||
element.timeout = timeout;
|
||||
element.reload_counter = times;
|
||||
if (times > 1){
|
||||
// Multiple or infinite reload
|
||||
// Run first iteration
|
||||
web2py_ajax_page('get', action, null, target);
|
||||
element.run_once = false;
|
||||
element.timing = setInterval(statement, timeout);
|
||||
element.reload_counter -= 1;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}; // reload check
|
||||
if(!isNaN(timeout)) {
|
||||
element.timeout = timeout;
|
||||
element.reload_counter = times;
|
||||
if(times > 1) {
|
||||
// Multiple or infinite reload
|
||||
// Run first iteration
|
||||
web2py.ajax_page('get', action, null, target, el);
|
||||
element.run_once = false;
|
||||
element.timing = setInterval(statement, timeout);
|
||||
element.reload_counter -= 1;
|
||||
} else if(times == 1) {
|
||||
// Run once with timeout
|
||||
element.run_once = true;
|
||||
element.setTimeout = setTimeout;
|
||||
element.timing = setTimeout(statement, timeout);
|
||||
}
|
||||
} else {
|
||||
// run once (no timeout specified)
|
||||
element.reload_counter = Infinity;
|
||||
web2py.ajax_page('get', action, null, target, el);
|
||||
}
|
||||
else if (times == 1) {
|
||||
// Run once with timeout
|
||||
element.run_once = true;
|
||||
element.setTimeout = setTimeout;
|
||||
element.timing = setTimeout(statement, timeout);
|
||||
});
|
||||
},
|
||||
calc_entropy: function (mystring) {
|
||||
//calculate a simple entropy for a given string
|
||||
var csets = new Array(
|
||||
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
'0123456789', '!@#$\%^&*()', '~`-_=+[]{}\|;:\'",.<>?/',
|
||||
'0123456789abcdefghijklmnopqrstuvwxyz');
|
||||
var score = 0,
|
||||
other = {}, seen = {}, lastset = null,
|
||||
mystringlist = mystring.split('');
|
||||
for(var i = 0; i < mystringlist.length; i++) { // classify this character
|
||||
var c = mystringlist[i],
|
||||
inset = 5;
|
||||
for(var j = 0; j < csets.length; j++)
|
||||
if(csets[j].indexOf(c) != -1) {
|
||||
inset = j;
|
||||
break;
|
||||
}
|
||||
//calculate effect of character on alphabet size
|
||||
if(!(inset in seen)) {
|
||||
seen[inset] = 1;
|
||||
score += csets[inset].length;
|
||||
} else if(!(c in other)) {
|
||||
score += 1;
|
||||
other[c] = 1;
|
||||
}
|
||||
} else {
|
||||
// run once (no timeout specified)
|
||||
element.reload_counter = Infinity;
|
||||
web2py_ajax_page('get', action, null, target);
|
||||
} }); }
|
||||
if(inset != lastset) {
|
||||
score += 1;
|
||||
lastset = inset;
|
||||
}
|
||||
}
|
||||
var entropy = mystring.length * Math.log(score) / 0.6931471805599453;
|
||||
return Math.round(entropy * 100) / 100
|
||||
},
|
||||
validate_entropy: function (myfield, req_entropy) {
|
||||
//added
|
||||
if(myfield.data('w2p_entropy') != undefined) req_entropy = myfield.data('w2p_entropy');
|
||||
var validator = function () {
|
||||
var v = (web2py.calc_entropy(myfield.val()) || 0) / req_entropy;
|
||||
var r = 0,
|
||||
g = 0,
|
||||
b = 0,
|
||||
rs = function (x) {
|
||||
return Math.round(x * 15).toString(16)
|
||||
};
|
||||
if(v <= 0.5) {
|
||||
r = 1.0;
|
||||
g = 2.0 * v;
|
||||
} else {
|
||||
r = (1.0 - 2.0 * (Math.max(v, 0) - 0.5));
|
||||
g = 1.0;
|
||||
}
|
||||
var color = '#' + rs(r) + rs(g) + rs(b);
|
||||
myfield.css('background-color', color);
|
||||
entropy_callback = myfield.data('entropy_callback');
|
||||
if(entropy_callback) entropy_callback(v);
|
||||
}
|
||||
if(!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator).addClass('entropy_check');
|
||||
},
|
||||
web2py_websocket: function (url, onmessage, onopen, onclose) {
|
||||
if("WebSocket" in window) {
|
||||
var ws = new WebSocket(url);
|
||||
ws.onopen = onopen ? onopen : (function () {});
|
||||
ws.onmessage = onmessage;
|
||||
ws.onclose = onclose ? onclose : (function () {});
|
||||
return true; // supported
|
||||
} else return false; // not supported
|
||||
},
|
||||
/* new from here */
|
||||
// Form input elements bound by jquery-ujs
|
||||
formInputClickSelector: 'input[type=submit], input[type=image], button[type=submit], button:not([type])',
|
||||
// Form input elements disabled during form submission
|
||||
disableSelector: 'input, button, textarea, select',
|
||||
// Form input elements re-enabled after form submission
|
||||
enableSelector: 'input:disabled, button:disabled, textarea:disabled, select:disabled',
|
||||
// Triggers an event on an element and returns false if the event result is false
|
||||
fire: function (obj, name, data) {
|
||||
var event = $.Event(name);
|
||||
obj.trigger(event, data);
|
||||
return event.result !== false;
|
||||
},
|
||||
// Helper function, needed to provide consistent behavior in IE
|
||||
stopEverything: function (e) {
|
||||
$(e.target).trigger('w2p:everythingStopped');
|
||||
e.stopImmediatePropagation();
|
||||
return false;
|
||||
},
|
||||
confirm: function (message) {
|
||||
return confirm(message);
|
||||
},
|
||||
// replace element's html with the 'data-disable-with' after storing original html
|
||||
// and prevent clicking on it
|
||||
disableElement: function (el) {
|
||||
el.addClass('disabled');
|
||||
var method = el.prop('type') == 'submit' ? 'val' : 'html';
|
||||
// store enabled state
|
||||
el.data('w2p:enable-with', el[method]);
|
||||
/* little addition by default*/
|
||||
if((el.data('w2p_disable_with') == 'default') || (el.data('w2p_disable_with') === undefined)) {
|
||||
el.data('w2p_disable_with', 'Working...');
|
||||
}
|
||||
// set to disabled state
|
||||
el[method](el.data('w2p_disable_with'));
|
||||
|
||||
function web2py_websocket(url,onmessage,onopen,onclose) {
|
||||
if ("WebSocket" in window) {
|
||||
var ws = new WebSocket(url);
|
||||
ws.onopen = onopen?onopen:(function(){});
|
||||
ws.onmessage = onmessage;
|
||||
ws.onclose = onclose?onclose:(function(){});
|
||||
return true; // supported
|
||||
} else return false; // not supported
|
||||
}
|
||||
el.bind('click.w2pDisable', function (e) { // prevent further clicking
|
||||
return web2py.stopEverything(e);
|
||||
});
|
||||
},
|
||||
|
||||
// restore element to its original state which was disabled by 'disableElement' above
|
||||
enableElement: function (el) {
|
||||
var method = el.prop('type') == 'submit' ? 'val' : 'html';
|
||||
if(el.data('w2p:enable-with') !== undefined) {
|
||||
// set to old enabled state
|
||||
el[method](el.data('w2p:enable-with'));
|
||||
el.removeData('w2p:enable-with'); // clean up cache
|
||||
}
|
||||
el.removeClass('disabled');
|
||||
el.unbind('click.w2pDisable'); // enable element
|
||||
},
|
||||
//convenience wrapper, internal use only
|
||||
simple_component: function (action, target, element) {
|
||||
web2py.component(action, target, 0, 1, element);
|
||||
},
|
||||
//helper for flash messages
|
||||
flash: function(message, status) {
|
||||
var flash = $('.flash');
|
||||
web2py.hide_flash();
|
||||
flash.html(message).addClass(status);
|
||||
if(flash.html()) flash.append('<span id="closeflash"> × </span>').slideDown();
|
||||
},
|
||||
hide_flash: function() {
|
||||
$('.flash').hide().html('');
|
||||
},
|
||||
show_if_handler: function(target) {
|
||||
var triggers = {};
|
||||
var show_if = function () {
|
||||
var t = $(this);
|
||||
var id = t.attr('id');
|
||||
t.attr('value', t.val());
|
||||
for(var k = 0; k < triggers[id].length; k++) {
|
||||
var dep = $('#' + triggers[id][k], target);
|
||||
var tr = $('#' + triggers[id][k] + '__row', target);
|
||||
if(t.is(dep.attr('data-show-if'))) tr.slideDown();
|
||||
else tr.hide();
|
||||
}
|
||||
};
|
||||
$('[data-show-trigger]', target).each(function () {
|
||||
var name = $(this).attr('data-show-trigger');
|
||||
if(!triggers[name]) triggers[name] = [];
|
||||
triggers[name].push($(this).attr('id'));
|
||||
});
|
||||
for(var name in triggers) {
|
||||
$('#' + name, target).change(show_if).keyup(show_if);
|
||||
show_if.call($('#' + name, target));
|
||||
};
|
||||
},
|
||||
component_handler : function (target) {
|
||||
$('div[data-w2p_remote]', target).each(function () {
|
||||
var remote, times, timeout, target;
|
||||
var el = $(this);
|
||||
remote = el.data('w2p_remote');
|
||||
times = el.data('w2p_times');
|
||||
timeout = el.data('w2p_timeout');
|
||||
target = el.attr('id');
|
||||
web2py.component(remote, target, timeout, times, $(this));
|
||||
}
|
||||
)
|
||||
},
|
||||
a_handler: function (el, e) {
|
||||
e.preventDefault();
|
||||
var method = el.data('w2p_method');
|
||||
var action = el.attr('href');
|
||||
var target = el.data('w2p_target');
|
||||
var confirm_message = el.data('w2p_confirm');
|
||||
|
||||
function web2py_calc_entropy(mystring) {
|
||||
//calculate a simple entropy for a given string
|
||||
var csets = new Array(
|
||||
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
'0123456789', '!@#$\%^&*()', '~`-_=+[]{}\|;:\'",.<>?/',
|
||||
'0123456789abcdefghijklmnopqrstuvwxyz');
|
||||
var score = 0, other = {}, seen = {}, lastset = null, mystringlist = mystring.split('');
|
||||
for (var i=0;i<mystringlist.length;i++) { // classify this character
|
||||
var c = mystringlist[i], inset=5;
|
||||
for(var j = 0; j<csets.length; j++)
|
||||
if (csets[j].indexOf(c) != -1) {inset = j; break;}
|
||||
//calculate effect of character on alphabet size
|
||||
if(!(inset in seen)) {seen[inset] = 1;score += csets[inset].length;}
|
||||
else if (!(c in other)) {score += 1;other[c] = 1;}
|
||||
if (inset != lastset) {score += 1;lastset = inset;}
|
||||
var pre_call = el.data('w2p_pre_call');
|
||||
if(pre_call != undefined) {
|
||||
eval(pre_call);
|
||||
}
|
||||
if(confirm_message != undefined) {
|
||||
if(confirm_message == 'default') confirm_message = w2p_ajax_confirm_message || 'Are you sure you want to delete this object?';
|
||||
if(!web2py.confirm(confirm_message)) {
|
||||
web2py.stopEverything(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(target == undefined) {
|
||||
if(method == 'GET') {
|
||||
web2py.simple_component(action, el.attr('id'), el); //not working with original
|
||||
} else if(method == 'POST') {
|
||||
//should be web2py.ajax(action, [], ''); but it's too simple
|
||||
web2py.ajax_page('post', action, [], 'bogus', el); //fixme?
|
||||
}
|
||||
} else {
|
||||
if(method == 'GET') {
|
||||
web2py.simple_component(action, target, el);
|
||||
} else if(method == 'POST') {
|
||||
//should be web2py.ajax(action, [], target); but it's too simple
|
||||
web2py.ajax_page('post', action, [], target, el);
|
||||
}
|
||||
}
|
||||
/*this should happen only on ajaxsuccess
|
||||
* and should block subsequent clicks until ajaxcomplete
|
||||
* NB: introduce the first incompatibility because normally
|
||||
* the element would be removed in either case
|
||||
/* removal code moved to the ajax:success event - START
|
||||
if(toremove != undefined) {
|
||||
toremove = el.closest(toremove);
|
||||
if(!toremove.length) {
|
||||
//this enables removal of whatever selector if a closest is not found
|
||||
toremove = $(toremove);
|
||||
}
|
||||
toremove.remove();
|
||||
}
|
||||
/* removal code moved to the ajax:success event - END */
|
||||
},
|
||||
a_handlers: function () {
|
||||
var el = $(document);
|
||||
el.on('click', 'a[data-w2p_method]', function (e) {
|
||||
web2py.a_handler($(this), e);
|
||||
});
|
||||
/* removal of element should happen only on success */
|
||||
el.on('ajax:success', 'a[data-w2p_method][data-w2p_remove]', function (e) {
|
||||
var el = $(this);
|
||||
var toremove = el.data('w2p_remove');
|
||||
if(toremove != undefined) {
|
||||
toremove = el.closest(toremove);
|
||||
if(!toremove.length) {
|
||||
//this enables removal of whatever selector if a closest is not found
|
||||
toremove = $(toremove);
|
||||
}
|
||||
toremove.remove();
|
||||
}
|
||||
});
|
||||
el.on('ajax:beforeSend', 'a[data-w2p_method][data-w2p_disable_with]', function (e) {
|
||||
web2py.disableElement($(this));
|
||||
});
|
||||
/*re-enable click on completion*/
|
||||
el.on('ajax:complete', 'a[data-w2p_method][data-w2p_disable_with]', function (e) {
|
||||
web2py.enableElement($(this));
|
||||
});
|
||||
},
|
||||
/* Disables form elements:
|
||||
- Caches element value in 'ujs:enable-with' data store
|
||||
- Replaces element text with value of 'data-disable-with' attribute
|
||||
- Sets disabled property to true
|
||||
*/
|
||||
disableFormElements: function(form) {
|
||||
form.find(web2py.disableSelector).each(function() {
|
||||
var element = $(this), method = element.is('button') ? 'html' : 'val';
|
||||
var disable_with = element.data('w2p_disable_with');
|
||||
if (disable_with == undefined) {
|
||||
element.data('w2p_disable_with', element[method]())
|
||||
}
|
||||
element.data('w2p:enable-with', element[method]());
|
||||
element[method](element.data('w2p_disable_with'));
|
||||
element.prop('disabled', true);
|
||||
});
|
||||
},
|
||||
|
||||
/* Re-enables disabled form elements:
|
||||
- Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
|
||||
- Sets disabled property to false
|
||||
*/
|
||||
enableFormElements: function(form) {
|
||||
form.find(web2py.enableSelector).each(function() {
|
||||
var element = $(this), method = element.is('button') ? 'html' : 'val';
|
||||
if (element.data('w2p:enable-with')) element[method](element.data('w2p:enable-with'));
|
||||
element.prop('disabled', false);
|
||||
});
|
||||
},
|
||||
form_handlers: function() {
|
||||
var el = $(document);
|
||||
el.on('ajax:beforeSend', 'form[data-w2p_target]', function (e) {
|
||||
web2py.disableFormElements($(this));
|
||||
});
|
||||
el.on('ajax:complete', 'form[data-w2p_target]', function (e) {
|
||||
web2py.enableFormElements($(this));
|
||||
});
|
||||
}
|
||||
var entropy = mystring.length*Math.log(score)/0.6931471805599453;
|
||||
return Math.round(entropy*100)/100
|
||||
}
|
||||
}
|
||||
|
||||
function web2py_validate_entropy(myfield, req_entropy) {
|
||||
var validator = function () {
|
||||
var v = (web2py_calc_entropy(myfield.val())||0)/req_entropy;
|
||||
var r=0,g=0,b=0,rs=function(x){return Math.round(x*15).toString(16)};
|
||||
if(v<=0.5) {r=1.0; g=2.0*v;}
|
||||
else {r=(1.0-2.0*(Math.max(v,0)-0.5)); g=1.0;}
|
||||
var color = '#'+rs(r)+rs(g)+rs(b);
|
||||
myfield.css('background-color',color);
|
||||
entropy_callback = myfield.data('entropy_callback');
|
||||
if(entropy_callback) entropy_callback(v);
|
||||
}
|
||||
if(!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator).addClass('entropy_check');
|
||||
}
|
||||
//end of functions
|
||||
//main hook
|
||||
$(function () {
|
||||
var flash = $('.flash');
|
||||
flash.hide();
|
||||
if(flash.html()) web2py.flash(flash.html());
|
||||
web2py.ajax_init(document);
|
||||
web2py.event_handlers();
|
||||
web2py.a_handlers();
|
||||
web2py.form_handlers();
|
||||
});
|
||||
|
||||
function web2py_show_if(target) {
|
||||
var triggers = {};
|
||||
var show_if = function () {
|
||||
var t = jQuery(this);
|
||||
var id = t.attr('id');
|
||||
t.attr('value', t.val());
|
||||
for(var k = 0; k < triggers[id].length; k++) {
|
||||
var dep = jQuery('#' + triggers[id][k], target);
|
||||
var tr = jQuery('#' + triggers[id][k] + '__row', target);
|
||||
if(t.is(dep.attr('data-show-if'))) tr.slideDown();
|
||||
else tr.hide();
|
||||
}
|
||||
};
|
||||
jQuery('[data-show-trigger]', target).each(function () {
|
||||
var name = jQuery(this).attr('data-show-trigger');
|
||||
if(!triggers[name]) triggers[name] = [];
|
||||
triggers[name].push(jQuery(this).attr('id'));
|
||||
});
|
||||
for(var name in triggers) {
|
||||
jQuery('#' + name, target).change(show_if).keyup(show_if);
|
||||
show_if.call(jQuery('#' + name, target));
|
||||
};
|
||||
}
|
||||
})(jQuery);
|
||||
|
||||
/* compatibility code - start */
|
||||
ajax = $.web2py.ajax;
|
||||
web2py_component = $.web2py.component;
|
||||
web2py_websocket = $.web2py.websocket;
|
||||
web2py_ajax_page = $.web2py.ajax_page;
|
||||
//needed for IS_STRONG(entropy)
|
||||
web2py_validate_entropy = $.web2py.validate_entropy;
|
||||
//needed for crud.search and SQLFORM.grid's search
|
||||
web2py_ajax_fields = $.web2py.ajax_fields;
|
||||
//used for LOAD(ajax=False)
|
||||
web2py_trap_form = $.web2py.trap_form;
|
||||
|
||||
/*undocumented - rare*/
|
||||
popup = $.web2py.popup;
|
||||
collapse = $.web2py.collapse;
|
||||
fade = $.web2py.fade;
|
||||
|
||||
/* internals - shouldn't be needed
|
||||
|
||||
web2py_ajax_init = $.web2py.ajax_init;
|
||||
web2py_event_handlers = $.web2py.event_handlers;
|
||||
|
||||
web2py_trap_link = $.web2py.trap_link;
|
||||
web2py_calc_entropy = $.web2py.calc_entropy;
|
||||
*/
|
||||
/* compatibility code - end*/
|
||||
|
||||
@@ -1,242 +1,653 @@
|
||||
function popup(url) {
|
||||
newwindow=window.open(url,'name','height=400,width=600');
|
||||
if (window.focus) newwindow.focus();
|
||||
return false;
|
||||
}
|
||||
function collapse(id) { jQuery('#'+id).slideToggle(); }
|
||||
function fade(id,value) { if(value>0) jQuery('#'+id).hide().fadeIn('slow'); else jQuery('#'+id).show().fadeOut('slow'); }
|
||||
function ajax(u,s,t) {
|
||||
query = '';
|
||||
if (typeof s == "string") {
|
||||
d = jQuery(s).serialize();
|
||||
if(d){ query = d; }
|
||||
} else {
|
||||
(function ($, undefined) {
|
||||
/*
|
||||
* Unobtrusive scripting adapter for jQuery, largely taken from
|
||||
* the wonderful https://github.com/rails/jquery-ujs
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
*
|
||||
*/
|
||||
|
||||
String.prototype.reverse = function () {
|
||||
return this.split('').reverse().join('');
|
||||
};
|
||||
var web2py;
|
||||
|
||||
$.web2py = web2py = {
|
||||
|
||||
popup: function (url) {
|
||||
newwindow = window.open(url, 'name', 'height=400,width=600');
|
||||
if(window.focus) newwindow.focus();
|
||||
return false;
|
||||
},
|
||||
collapse: function (id) {
|
||||
$('#' + id).slideToggle();
|
||||
},
|
||||
fade: function (id, value) {
|
||||
if(value > 0) $('#' + id).hide().fadeIn('slow');
|
||||
else $('#' + id).show().fadeOut('slow');
|
||||
},
|
||||
ajax: function (u, s, t) {
|
||||
query = '';
|
||||
if(typeof s == "string") {
|
||||
d = $(s).serialize();
|
||||
if(d) {
|
||||
query = d;
|
||||
}
|
||||
} else {
|
||||
pcs = [];
|
||||
if (s != null && s != undefined) for(i=0; i<s.length; i++) {
|
||||
q = jQuery("[name="+s[i]+"]").serialize();
|
||||
if(q){pcs.push(q);}
|
||||
if(s != null && s != undefined) for(i = 0; i < s.length; i++) {
|
||||
q = $("[name=" + s[i] + "]").serialize();
|
||||
if(q) {
|
||||
pcs.push(q);
|
||||
}
|
||||
}
|
||||
if(pcs.length > 0) {
|
||||
query = pcs.join("&");
|
||||
}
|
||||
if (pcs.length>0){query = pcs.join("&");}
|
||||
}
|
||||
jQuery.ajax({type: "POST", url: u, data: query, success: function(msg) { if(t) { if(t==':eval') eval(msg); else if(typeof t=='string') jQuery("#"+t).html(msg); else t(msg); } } });
|
||||
}
|
||||
|
||||
String.prototype.reverse = function () { return this.split('').reverse().join('');};
|
||||
function web2py_ajax_fields(target) {
|
||||
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
||||
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
||||
jQuery("input.date",target).each(function() {Calendar.setup({inputField:this, ifFormat:date_format, showsTime:false });});
|
||||
jQuery("input.datetime",target).each(function() {Calendar.setup({inputField:this, ifFormat:datetime_format, showsTime: true, timeFormat: "24" });});
|
||||
jQuery("input.time",target).each(function(){jQuery(this).timeEntry();});
|
||||
|
||||
};
|
||||
|
||||
function web2py_ajax_init(target) {
|
||||
jQuery('.hidden', target).hide();
|
||||
jQuery('.error', target).hide().slideDown('slow');
|
||||
web2py_ajax_fields(target);
|
||||
web2py_show_if(target);
|
||||
};
|
||||
|
||||
function web2py_event_handlers() {
|
||||
var doc = jQuery(document)
|
||||
doc.on('click', '.flash', function(e){var t=jQuery(this); if(t.css('top')=='0px') t.slideUp('slow'); else t.fadeOut(); e.preventDefault();});
|
||||
doc.on('keyup', 'input.integer', function(){this.value=this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g,'').reverse();});
|
||||
doc.on('keyup', 'input.double, input.decimal', function(){this.value=this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g,'').reverse();});
|
||||
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
|
||||
doc.on('click', "input[type='checkbox'].delete", function(){if(this.checked) if(!confirm(confirm_message)) this.checked=false;});
|
||||
|
||||
doc.ajaxSuccess(function(e, xhr) {
|
||||
var redirect=xhr.getResponseHeader('web2py-redirect-location');
|
||||
var command=xhr.getResponseHeader('web2py-component-command');
|
||||
var flash=xhr.getResponseHeader('web2py-component-flash');
|
||||
if (redirect !== null) {
|
||||
window.location = redirect;
|
||||
};
|
||||
if(command !== null){
|
||||
eval(decodeURIComponent(command));
|
||||
}
|
||||
if(flash) {
|
||||
jQuery('.flash')
|
||||
.html(decodeURIComponent(flash))
|
||||
.append('<span id="closeflash">×</span>')
|
||||
.slideDown();
|
||||
}
|
||||
});
|
||||
|
||||
doc.ajaxError(function(e, xhr, settings, exception) {
|
||||
doc.off('click', '.flash')
|
||||
switch(xhr.status){
|
||||
case 500:
|
||||
$('.flash').html(ajax_error_500).slideDown();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
jQuery(function() {
|
||||
var flash = jQuery('.flash');
|
||||
flash.hide();
|
||||
if(flash.html()) flash.append('<span id="closeflash">×</span>').slideDown();
|
||||
web2py_ajax_init(document);
|
||||
web2py_event_handlers();
|
||||
});
|
||||
|
||||
function web2py_trap_form(action,target) {
|
||||
jQuery('#'+target+' form').each(function(i){
|
||||
var form=jQuery(this);
|
||||
if(!form.hasClass('no_trap'))
|
||||
form.submit(function(e){
|
||||
jQuery('.flash').hide().html('');
|
||||
web2py_ajax_page('post',action,form.serialize(),target);
|
||||
e.preventDefault();
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: u,
|
||||
data: query,
|
||||
success: function (msg) {
|
||||
if(t) {
|
||||
if(t == ':eval') eval(msg);
|
||||
else if(typeof t == 'string') $("#" + t).html(msg);
|
||||
else t(msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function web2py_trap_link(target) {
|
||||
jQuery('#'+target+' a.w2p_trap').each(function(i){
|
||||
var link=jQuery(this);
|
||||
link.click(function(e) {
|
||||
jQuery('.flash').hide().html('');
|
||||
web2py_ajax_page('get',link.attr('href'),[],target);
|
||||
e.preventDefault();
|
||||
});
|
||||
},
|
||||
ajax_fields: function (target) {
|
||||
/*this attaches something to a newly loaded fragment/page
|
||||
* Ideally all events should be bound to the document, so we can avoid calling
|
||||
* this over and over... all will be bound to the document
|
||||
*/
|
||||
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
||||
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
||||
$("input.date", target).each(function () {
|
||||
Calendar.setup({
|
||||
inputField: this,
|
||||
ifFormat: date_format,
|
||||
showsTime: false
|
||||
});
|
||||
}
|
||||
});
|
||||
$("input.datetime", target).each(function () {
|
||||
Calendar.setup({
|
||||
inputField: this,
|
||||
ifFormat: datetime_format,
|
||||
showsTime: true,
|
||||
timeFormat: "24"
|
||||
});
|
||||
});
|
||||
$("input.time", target).each(function () {
|
||||
$(this).timeEntry();
|
||||
});
|
||||
/*adds btn class to buttons*/
|
||||
$('button', target).addClass('btn');
|
||||
$('form input[type="submit"], form input[type="button"]', target).addClass('btn');
|
||||
/*no more inline javascript for PasswordWidget*/
|
||||
$('input[type=password][data-w2p_entropy]', target).each(function () {
|
||||
web2py.validate_entropy($(this));
|
||||
});
|
||||
/*no more inline javascript for ListWidget*/
|
||||
$('ul.w2p_list', target).each(function () {
|
||||
function pe(ul, e) {
|
||||
var new_line = ml(ul);
|
||||
rel(ul);
|
||||
if($(e.target).parent().is(':visible')) {
|
||||
//make sure we didn't delete the element before we insert after
|
||||
new_line.insertAfter($(e.target).parent());
|
||||
} else {
|
||||
//the line we clicked on was deleted, just add to end of list
|
||||
new_line.appendTo(ul);
|
||||
}
|
||||
new_line.find(":text").focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
function web2py_ajax_page(method, action, data, target) {
|
||||
jQuery.ajax({'type':method, 'url':action, 'data':data,
|
||||
'beforeSend':function(xhr) {
|
||||
xhr.setRequestHeader('web2py-component-location', document.location);
|
||||
xhr.setRequestHeader('web2py-component-element', target);},
|
||||
'complete':function(xhr,text){
|
||||
var html=xhr.responseText;
|
||||
var content=xhr.getResponseHeader('web2py-component-content');
|
||||
var t = jQuery('#'+target);
|
||||
if(content=='prepend') t.prepend(html);
|
||||
else if(content=='append') t.append(html);
|
||||
else if(content!='hide') t.html(html);
|
||||
web2py_trap_form(action,target);
|
||||
web2py_trap_link(target);
|
||||
web2py_ajax_init('#'+target);
|
||||
}
|
||||
});
|
||||
}
|
||||
function rl(ul, e) {
|
||||
if($(ul).children().length > 1) {
|
||||
//only remove if we have more than 1 item so the list is never empty
|
||||
$(e.target).parent().remove();
|
||||
}
|
||||
}
|
||||
|
||||
function web2py_component(action, target, timeout, times){
|
||||
jQuery(function(){
|
||||
var jelement = jQuery("#" + target);
|
||||
var element = jelement.get(0);
|
||||
var statement = "jQuery('#" + target + "').get(0).reload();";
|
||||
jelement.reload = function (){
|
||||
// Continue if times is Infinity or
|
||||
// the times limit is not reached
|
||||
if (element.reload_check()){
|
||||
web2py_ajax_page('get', action, null, target);} }; // reload
|
||||
// Method to check timing limit
|
||||
element.reload_check = function (){
|
||||
if (jelement.hasClass('w2p_component_stop')) {clearInterval(this.timing);return false;}
|
||||
if (this.reload_counter == Infinity){return true;}
|
||||
else {
|
||||
if (!isNaN(this.reload_counter)){
|
||||
this.reload_counter -= 1;
|
||||
if (this.reload_counter < 0){
|
||||
if (!this.run_once){
|
||||
clearInterval(this.timing);
|
||||
return false;
|
||||
}
|
||||
function ml(ul) {
|
||||
var line = $(ul).find("li:first").clone(true);
|
||||
line.find(':text').val('');
|
||||
return line;
|
||||
}
|
||||
|
||||
function rel(ul) {
|
||||
$(ul).find("li").each(function () {
|
||||
var trimmed = $.trim($(this.firstChild).val());
|
||||
if(trimmed == '') $(this).remove();
|
||||
else $(this.firstChild).val(trimmed);
|
||||
});
|
||||
}
|
||||
var ul = this;
|
||||
$(ul).find(":text").after('<a href="#">+</a> <a href="#">-</a>').keypress(function (e) {
|
||||
return(e.which == 13) ? pe(ul, e) : true;
|
||||
}).next().click(function (e) {
|
||||
pe(ul, e);
|
||||
e.preventDefault();
|
||||
}).next().click(function (e) {
|
||||
rl(ul, e);
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
},
|
||||
ajax_init: function (target) {
|
||||
$('.hidden', target).hide();
|
||||
web2py.manage_errors(target);
|
||||
web2py.ajax_fields(target);
|
||||
web2py.show_if_handler(target);
|
||||
web2py.component_handler(target);
|
||||
},
|
||||
//manage errors in forms
|
||||
manage_errors: function(target) {
|
||||
$('.error', target).hide().slideDown('slow');
|
||||
//$('.error', target).hide().fadeIn('slow');
|
||||
},
|
||||
event_handlers: function () {
|
||||
/* This is called once for page
|
||||
* Ideally it should bound all the things that are needed
|
||||
*/
|
||||
var doc = $(document);
|
||||
doc.on('click', '.flash', function (e) {
|
||||
var t = $(this);
|
||||
if(t.css('top') == '0px') t.slideUp('slow');
|
||||
else t.fadeOut();
|
||||
//if I want to display a clickable something
|
||||
//inside flash, I should not be prevented to follow it
|
||||
//e.preventDefault();
|
||||
});
|
||||
doc.on('keyup', 'input.integer', function () {
|
||||
this.value = this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g, '').reverse();
|
||||
});
|
||||
doc.on('keyup', 'input.double, input.decimal', function () {
|
||||
this.value = this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g, '').reverse();
|
||||
});
|
||||
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
|
||||
doc.on('click', "input[type='checkbox'].delete", function () {
|
||||
if(this.checked) if(!web2py.confirm(confirm_message)) this.checked = false;
|
||||
});
|
||||
|
||||
doc.ajaxSuccess(function (e, xhr) {
|
||||
var redirect = xhr.getResponseHeader('web2py-redirect-location');
|
||||
var command = xhr.getResponseHeader('web2py-component-command');
|
||||
var flash = xhr.getResponseHeader('web2py-component-flash');
|
||||
if(redirect !== null) {
|
||||
window.location = redirect;
|
||||
};
|
||||
if(command !== null) {
|
||||
eval(decodeURIComponent(command));
|
||||
}
|
||||
if(flash) {
|
||||
web2py.flash(decodeURIComponent(flash))
|
||||
}
|
||||
});
|
||||
|
||||
doc.ajaxError(function (e, xhr, settings, exception) {
|
||||
//personally I don't like it.
|
||||
//if there's an error it it flashed and can be removed
|
||||
//as any other message
|
||||
//doc.off('click', '.flash')
|
||||
switch(xhr.status) {
|
||||
case 500:
|
||||
web2py.flash(ajax_error_500);
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
trap_form: function (action, target) {
|
||||
$('#' + target + ' form').each(function (i) {
|
||||
var form = $(this);
|
||||
form.attr('data-w2p_target', target);
|
||||
if(!form.hasClass('no_trap')) {
|
||||
//should be there by default ?
|
||||
form.find('input[type=submit]').attr('data-w2p_disable_with', 'Working...');
|
||||
form.submit(function (e) {
|
||||
web2py.hide_flash();
|
||||
web2py.ajax_page('post', action, form.serialize(), target, form);
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
trap_link: function (target) {
|
||||
$('#' + target + ' a.w2p_trap').each(function (i) {
|
||||
var link = $(this);
|
||||
link.click(function (e) {
|
||||
web2py.hide_flash();
|
||||
web2py.ajax_page('get', link.attr('href'), [], target);
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
},
|
||||
ajax_page: function (method, action, data, target, element) {
|
||||
//element is a new parameter, but should be put be put in front
|
||||
if(element == undefined) element = $(document);
|
||||
if(web2py.fire(element, 'ajax:before')) { //test a usecase, should stop here if returns false
|
||||
$.ajax({
|
||||
'type': method,
|
||||
'url': action,
|
||||
'data': data,
|
||||
'beforeSend': function (xhr, settings) {
|
||||
//added
|
||||
xhr.setRequestHeader('web2py-component-location', document.location);
|
||||
xhr.setRequestHeader('web2py-component-element', target);
|
||||
return web2py.fire(element, 'ajax:beforeSend', [xhr, settings]); //test a usecase, should stop here if returns false
|
||||
},
|
||||
//added
|
||||
'success': function (data, status, xhr) {
|
||||
//bummer for form submissions....the element is not there after complete
|
||||
//because it gets replaced by the new response....
|
||||
element.trigger('ajax:success', [data, status, xhr]);
|
||||
},
|
||||
//added
|
||||
'error': function (xhr, status, error) {
|
||||
//bummer for form submissions....in addition to the element being not there after
|
||||
//complete because it gets replaced by the new response, standard form
|
||||
//handling just returns the same status code for good and bad
|
||||
//form submissions (i.e. that triggered a validator error)
|
||||
element.trigger('ajax:error', [xhr, status, error]);
|
||||
},
|
||||
'complete': function (xhr, status) {
|
||||
element.trigger('ajax:complete', [xhr, status]);
|
||||
var html = xhr.responseText;
|
||||
var content = xhr.getResponseHeader('web2py-component-content');
|
||||
var t = $('#' + target);
|
||||
if(content == 'prepend') t.prepend(html);
|
||||
else if(content == 'append') t.append(html);
|
||||
else if(content != 'hide') t.html(html);
|
||||
web2py.trap_form(action, target);
|
||||
web2py.trap_link(target);
|
||||
web2py.ajax_init('#' + target);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
component: function (action, target, timeout, times, el) {
|
||||
//element is a new parameter, but should be put in front
|
||||
$(function () {
|
||||
var jelement = $("#" + target);
|
||||
var element = jelement.get(0);
|
||||
var statement = "jQuery('#" + target + "').get(0).reload();";
|
||||
element.reload = function () {
|
||||
// Continue if times is Infinity or
|
||||
// the times limit is not reached
|
||||
if(element.reload_check()) {
|
||||
web2py.ajax_page('get', action, null, target, el);
|
||||
}
|
||||
}; // reload
|
||||
// Method to check timing limit
|
||||
element.reload_check = function () {
|
||||
if(jelement.hasClass('w2p_component_stop')) {
|
||||
clearInterval(this.timing);
|
||||
return false;
|
||||
}
|
||||
if(this.reload_counter == Infinity) {
|
||||
return true;
|
||||
} else {
|
||||
if(!isNaN(this.reload_counter)) {
|
||||
this.reload_counter -= 1;
|
||||
if(this.reload_counter < 0) {
|
||||
if(!this.run_once) {
|
||||
clearInterval(this.timing);
|
||||
return false;
|
||||
}
|
||||
else{return true;}
|
||||
} }
|
||||
return false;}; // reload check
|
||||
if (!isNaN(timeout)){
|
||||
element.timeout = timeout;
|
||||
element.reload_counter = times;
|
||||
if (times > 1){
|
||||
// Multiple or infinite reload
|
||||
// Run first iteration
|
||||
web2py_ajax_page('get', action, null, target);
|
||||
element.run_once = false;
|
||||
element.timing = setInterval(statement, timeout);
|
||||
element.reload_counter -= 1;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}; // reload check
|
||||
if(!isNaN(timeout)) {
|
||||
element.timeout = timeout;
|
||||
element.reload_counter = times;
|
||||
if(times > 1) {
|
||||
// Multiple or infinite reload
|
||||
// Run first iteration
|
||||
web2py.ajax_page('get', action, null, target, el);
|
||||
element.run_once = false;
|
||||
element.timing = setInterval(statement, timeout);
|
||||
element.reload_counter -= 1;
|
||||
} else if(times == 1) {
|
||||
// Run once with timeout
|
||||
element.run_once = true;
|
||||
element.setTimeout = setTimeout;
|
||||
element.timing = setTimeout(statement, timeout);
|
||||
}
|
||||
} else {
|
||||
// run once (no timeout specified)
|
||||
element.reload_counter = Infinity;
|
||||
web2py.ajax_page('get', action, null, target, el);
|
||||
}
|
||||
else if (times == 1) {
|
||||
// Run once with timeout
|
||||
element.run_once = true;
|
||||
element.setTimeout = setTimeout;
|
||||
element.timing = setTimeout(statement, timeout);
|
||||
});
|
||||
},
|
||||
calc_entropy: function (mystring) {
|
||||
//calculate a simple entropy for a given string
|
||||
var csets = new Array(
|
||||
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
'0123456789', '!@#$\%^&*()', '~`-_=+[]{}\|;:\'",.<>?/',
|
||||
'0123456789abcdefghijklmnopqrstuvwxyz');
|
||||
var score = 0,
|
||||
other = {}, seen = {}, lastset = null,
|
||||
mystringlist = mystring.split('');
|
||||
for(var i = 0; i < mystringlist.length; i++) { // classify this character
|
||||
var c = mystringlist[i],
|
||||
inset = 5;
|
||||
for(var j = 0; j < csets.length; j++)
|
||||
if(csets[j].indexOf(c) != -1) {
|
||||
inset = j;
|
||||
break;
|
||||
}
|
||||
//calculate effect of character on alphabet size
|
||||
if(!(inset in seen)) {
|
||||
seen[inset] = 1;
|
||||
score += csets[inset].length;
|
||||
} else if(!(c in other)) {
|
||||
score += 1;
|
||||
other[c] = 1;
|
||||
}
|
||||
} else {
|
||||
// run once (no timeout specified)
|
||||
element.reload_counter = Infinity;
|
||||
web2py_ajax_page('get', action, null, target);
|
||||
} }); }
|
||||
if(inset != lastset) {
|
||||
score += 1;
|
||||
lastset = inset;
|
||||
}
|
||||
}
|
||||
var entropy = mystring.length * Math.log(score) / 0.6931471805599453;
|
||||
return Math.round(entropy * 100) / 100
|
||||
},
|
||||
validate_entropy: function (myfield, req_entropy) {
|
||||
//added
|
||||
if(myfield.data('w2p_entropy') != undefined) req_entropy = myfield.data('w2p_entropy');
|
||||
var validator = function () {
|
||||
var v = (web2py.calc_entropy(myfield.val()) || 0) / req_entropy;
|
||||
var r = 0,
|
||||
g = 0,
|
||||
b = 0,
|
||||
rs = function (x) {
|
||||
return Math.round(x * 15).toString(16)
|
||||
};
|
||||
if(v <= 0.5) {
|
||||
r = 1.0;
|
||||
g = 2.0 * v;
|
||||
} else {
|
||||
r = (1.0 - 2.0 * (Math.max(v, 0) - 0.5));
|
||||
g = 1.0;
|
||||
}
|
||||
var color = '#' + rs(r) + rs(g) + rs(b);
|
||||
myfield.css('background-color', color);
|
||||
entropy_callback = myfield.data('entropy_callback');
|
||||
if(entropy_callback) entropy_callback(v);
|
||||
}
|
||||
if(!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator).addClass('entropy_check');
|
||||
},
|
||||
web2py_websocket: function (url, onmessage, onopen, onclose) {
|
||||
if("WebSocket" in window) {
|
||||
var ws = new WebSocket(url);
|
||||
ws.onopen = onopen ? onopen : (function () {});
|
||||
ws.onmessage = onmessage;
|
||||
ws.onclose = onclose ? onclose : (function () {});
|
||||
return true; // supported
|
||||
} else return false; // not supported
|
||||
},
|
||||
/* new from here */
|
||||
// Form input elements bound by jquery-ujs
|
||||
formInputClickSelector: 'input[type=submit], input[type=image], button[type=submit], button:not([type])',
|
||||
// Form input elements disabled during form submission
|
||||
disableSelector: 'input, button, textarea, select',
|
||||
// Form input elements re-enabled after form submission
|
||||
enableSelector: 'input:disabled, button:disabled, textarea:disabled, select:disabled',
|
||||
// Triggers an event on an element and returns false if the event result is false
|
||||
fire: function (obj, name, data) {
|
||||
var event = $.Event(name);
|
||||
obj.trigger(event, data);
|
||||
return event.result !== false;
|
||||
},
|
||||
// Helper function, needed to provide consistent behavior in IE
|
||||
stopEverything: function (e) {
|
||||
$(e.target).trigger('w2p:everythingStopped');
|
||||
e.stopImmediatePropagation();
|
||||
return false;
|
||||
},
|
||||
confirm: function (message) {
|
||||
return confirm(message);
|
||||
},
|
||||
// replace element's html with the 'data-disable-with' after storing original html
|
||||
// and prevent clicking on it
|
||||
disableElement: function (el) {
|
||||
el.addClass('disabled');
|
||||
var method = el.prop('type') == 'submit' ? 'val' : 'html';
|
||||
// store enabled state
|
||||
el.data('w2p:enable-with', el[method]);
|
||||
/* little addition by default*/
|
||||
if((el.data('w2p_disable_with') == 'default') || (el.data('w2p_disable_with') === undefined)) {
|
||||
el.data('w2p_disable_with', 'Working...');
|
||||
}
|
||||
// set to disabled state
|
||||
el[method](el.data('w2p_disable_with'));
|
||||
|
||||
function web2py_websocket(url,onmessage,onopen,onclose) {
|
||||
if ("WebSocket" in window) {
|
||||
var ws = new WebSocket(url);
|
||||
ws.onopen = onopen?onopen:(function(){});
|
||||
ws.onmessage = onmessage;
|
||||
ws.onclose = onclose?onclose:(function(){});
|
||||
return true; // supported
|
||||
} else return false; // not supported
|
||||
}
|
||||
el.bind('click.w2pDisable', function (e) { // prevent further clicking
|
||||
return web2py.stopEverything(e);
|
||||
});
|
||||
},
|
||||
|
||||
// restore element to its original state which was disabled by 'disableElement' above
|
||||
enableElement: function (el) {
|
||||
var method = el.prop('type') == 'submit' ? 'val' : 'html';
|
||||
if(el.data('w2p:enable-with') !== undefined) {
|
||||
// set to old enabled state
|
||||
el[method](el.data('w2p:enable-with'));
|
||||
el.removeData('w2p:enable-with'); // clean up cache
|
||||
}
|
||||
el.removeClass('disabled');
|
||||
el.unbind('click.w2pDisable'); // enable element
|
||||
},
|
||||
//convenience wrapper, internal use only
|
||||
simple_component: function (action, target, element) {
|
||||
web2py.component(action, target, 0, 1, element);
|
||||
},
|
||||
//helper for flash messages
|
||||
flash: function(message, status) {
|
||||
var flash = $('.flash');
|
||||
web2py.hide_flash();
|
||||
flash.html(message).addClass(status);
|
||||
if(flash.html()) flash.append('<span id="closeflash"> × </span>').slideDown();
|
||||
},
|
||||
hide_flash: function() {
|
||||
$('.flash').hide().html('');
|
||||
},
|
||||
show_if_handler: function(target) {
|
||||
var triggers = {};
|
||||
var show_if = function () {
|
||||
var t = $(this);
|
||||
var id = t.attr('id');
|
||||
t.attr('value', t.val());
|
||||
for(var k = 0; k < triggers[id].length; k++) {
|
||||
var dep = $('#' + triggers[id][k], target);
|
||||
var tr = $('#' + triggers[id][k] + '__row', target);
|
||||
if(t.is(dep.attr('data-show-if'))) tr.slideDown();
|
||||
else tr.hide();
|
||||
}
|
||||
};
|
||||
$('[data-show-trigger]', target).each(function () {
|
||||
var name = $(this).attr('data-show-trigger');
|
||||
if(!triggers[name]) triggers[name] = [];
|
||||
triggers[name].push($(this).attr('id'));
|
||||
});
|
||||
for(var name in triggers) {
|
||||
$('#' + name, target).change(show_if).keyup(show_if);
|
||||
show_if.call($('#' + name, target));
|
||||
};
|
||||
},
|
||||
component_handler : function (target) {
|
||||
$('div[data-w2p_remote]', target).each(function () {
|
||||
var remote, times, timeout, target;
|
||||
var el = $(this);
|
||||
remote = el.data('w2p_remote');
|
||||
times = el.data('w2p_times');
|
||||
timeout = el.data('w2p_timeout');
|
||||
target = el.attr('id');
|
||||
web2py.component(remote, target, timeout, times, $(this));
|
||||
}
|
||||
)
|
||||
},
|
||||
a_handler: function (el, e) {
|
||||
e.preventDefault();
|
||||
var method = el.data('w2p_method');
|
||||
var action = el.attr('href');
|
||||
var target = el.data('w2p_target');
|
||||
var confirm_message = el.data('w2p_confirm');
|
||||
|
||||
function web2py_calc_entropy(mystring) {
|
||||
//calculate a simple entropy for a given string
|
||||
var csets = new Array(
|
||||
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
'0123456789', '!@#$\%^&*()', '~`-_=+[]{}\|;:\'",.<>?/',
|
||||
'0123456789abcdefghijklmnopqrstuvwxyz');
|
||||
var score = 0, other = {}, seen = {}, lastset = null, mystringlist = mystring.split('');
|
||||
for (var i=0;i<mystringlist.length;i++) { // classify this character
|
||||
var c = mystringlist[i], inset=5;
|
||||
for(var j = 0; j<csets.length; j++)
|
||||
if (csets[j].indexOf(c) != -1) {inset = j; break;}
|
||||
//calculate effect of character on alphabet size
|
||||
if(!(inset in seen)) {seen[inset] = 1;score += csets[inset].length;}
|
||||
else if (!(c in other)) {score += 1;other[c] = 1;}
|
||||
if (inset != lastset) {score += 1;lastset = inset;}
|
||||
var pre_call = el.data('w2p_pre_call');
|
||||
if(pre_call != undefined) {
|
||||
eval(pre_call);
|
||||
}
|
||||
if(confirm_message != undefined) {
|
||||
if(confirm_message == 'default') confirm_message = w2p_ajax_confirm_message || 'Are you sure you want to delete this object?';
|
||||
if(!web2py.confirm(confirm_message)) {
|
||||
web2py.stopEverything(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(target == undefined) {
|
||||
if(method == 'GET') {
|
||||
web2py.simple_component(action, el.attr('id'), el); //not working with original
|
||||
} else if(method == 'POST') {
|
||||
//should be web2py.ajax(action, [], ''); but it's too simple
|
||||
web2py.ajax_page('post', action, [], 'bogus', el); //fixme?
|
||||
}
|
||||
} else {
|
||||
if(method == 'GET') {
|
||||
web2py.simple_component(action, target, el);
|
||||
} else if(method == 'POST') {
|
||||
//should be web2py.ajax(action, [], target); but it's too simple
|
||||
web2py.ajax_page('post', action, [], target, el);
|
||||
}
|
||||
}
|
||||
/*this should happen only on ajaxsuccess
|
||||
* and should block subsequent clicks until ajaxcomplete
|
||||
* NB: introduce the first incompatibility because normally
|
||||
* the element would be removed in either case
|
||||
/* removal code moved to the ajax:success event - START
|
||||
if(toremove != undefined) {
|
||||
toremove = el.closest(toremove);
|
||||
if(!toremove.length) {
|
||||
//this enables removal of whatever selector if a closest is not found
|
||||
toremove = $(toremove);
|
||||
}
|
||||
toremove.remove();
|
||||
}
|
||||
/* removal code moved to the ajax:success event - END */
|
||||
},
|
||||
a_handlers: function () {
|
||||
var el = $(document);
|
||||
el.on('click', 'a[data-w2p_method]', function (e) {
|
||||
web2py.a_handler($(this), e);
|
||||
});
|
||||
/* removal of element should happen only on success */
|
||||
el.on('ajax:success', 'a[data-w2p_method][data-w2p_remove]', function (e) {
|
||||
var el = $(this);
|
||||
var toremove = el.data('w2p_remove');
|
||||
if(toremove != undefined) {
|
||||
toremove = el.closest(toremove);
|
||||
if(!toremove.length) {
|
||||
//this enables removal of whatever selector if a closest is not found
|
||||
toremove = $(toremove);
|
||||
}
|
||||
toremove.remove();
|
||||
}
|
||||
});
|
||||
el.on('ajax:beforeSend', 'a[data-w2p_method][data-w2p_disable_with]', function (e) {
|
||||
web2py.disableElement($(this));
|
||||
});
|
||||
/*re-enable click on completion*/
|
||||
el.on('ajax:complete', 'a[data-w2p_method][data-w2p_disable_with]', function (e) {
|
||||
web2py.enableElement($(this));
|
||||
});
|
||||
},
|
||||
/* Disables form elements:
|
||||
- Caches element value in 'ujs:enable-with' data store
|
||||
- Replaces element text with value of 'data-disable-with' attribute
|
||||
- Sets disabled property to true
|
||||
*/
|
||||
disableFormElements: function(form) {
|
||||
form.find(web2py.disableSelector).each(function() {
|
||||
var element = $(this), method = element.is('button') ? 'html' : 'val';
|
||||
var disable_with = element.data('w2p_disable_with');
|
||||
if (disable_with == undefined) {
|
||||
element.data('w2p_disable_with', element[method]())
|
||||
}
|
||||
element.data('w2p:enable-with', element[method]());
|
||||
element[method](element.data('w2p_disable_with'));
|
||||
element.prop('disabled', true);
|
||||
});
|
||||
},
|
||||
|
||||
/* Re-enables disabled form elements:
|
||||
- Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
|
||||
- Sets disabled property to false
|
||||
*/
|
||||
enableFormElements: function(form) {
|
||||
form.find(web2py.enableSelector).each(function() {
|
||||
var element = $(this), method = element.is('button') ? 'html' : 'val';
|
||||
if (element.data('w2p:enable-with')) element[method](element.data('w2p:enable-with'));
|
||||
element.prop('disabled', false);
|
||||
});
|
||||
},
|
||||
form_handlers: function() {
|
||||
var el = $(document);
|
||||
el.on('ajax:beforeSend', 'form[data-w2p_target]', function (e) {
|
||||
web2py.disableFormElements($(this));
|
||||
});
|
||||
el.on('ajax:complete', 'form[data-w2p_target]', function (e) {
|
||||
web2py.enableFormElements($(this));
|
||||
});
|
||||
}
|
||||
var entropy = mystring.length*Math.log(score)/0.6931471805599453;
|
||||
return Math.round(entropy*100)/100
|
||||
}
|
||||
}
|
||||
|
||||
function web2py_validate_entropy(myfield, req_entropy) {
|
||||
var validator = function () {
|
||||
var v = (web2py_calc_entropy(myfield.val())||0)/req_entropy;
|
||||
var r=0,g=0,b=0,rs=function(x){return Math.round(x*15).toString(16)};
|
||||
if(v<=0.5) {r=1.0; g=2.0*v;}
|
||||
else {r=(1.0-2.0*(Math.max(v,0)-0.5)); g=1.0;}
|
||||
var color = '#'+rs(r)+rs(g)+rs(b);
|
||||
myfield.css('background-color',color);
|
||||
entropy_callback = myfield.data('entropy_callback');
|
||||
if(entropy_callback) entropy_callback(v);
|
||||
}
|
||||
if(!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator).addClass('entropy_check');
|
||||
}
|
||||
//end of functions
|
||||
//main hook
|
||||
$(function () {
|
||||
var flash = $('.flash');
|
||||
flash.hide();
|
||||
if(flash.html()) web2py.flash(flash.html());
|
||||
web2py.ajax_init(document);
|
||||
web2py.event_handlers();
|
||||
web2py.a_handlers();
|
||||
web2py.form_handlers();
|
||||
});
|
||||
|
||||
function web2py_show_if(target) {
|
||||
var triggers = {};
|
||||
var show_if = function () {
|
||||
var t = jQuery(this);
|
||||
var id = t.attr('id');
|
||||
t.attr('value', t.val());
|
||||
for(var k = 0; k < triggers[id].length; k++) {
|
||||
var dep = jQuery('#' + triggers[id][k], target);
|
||||
var tr = jQuery('#' + triggers[id][k] + '__row', target);
|
||||
if(t.is(dep.attr('data-show-if'))) tr.slideDown();
|
||||
else tr.hide();
|
||||
}
|
||||
};
|
||||
jQuery('[data-show-trigger]', target).each(function () {
|
||||
var name = jQuery(this).attr('data-show-trigger');
|
||||
if(!triggers[name]) triggers[name] = [];
|
||||
triggers[name].push(jQuery(this).attr('id'));
|
||||
});
|
||||
for(var name in triggers) {
|
||||
jQuery('#' + name, target).change(show_if).keyup(show_if);
|
||||
show_if.call(jQuery('#' + name, target));
|
||||
};
|
||||
}
|
||||
})(jQuery);
|
||||
|
||||
/* compatibility code - start */
|
||||
ajax = $.web2py.ajax;
|
||||
web2py_component = $.web2py.component;
|
||||
web2py_websocket = $.web2py.websocket;
|
||||
web2py_ajax_page = $.web2py.ajax_page;
|
||||
//needed for IS_STRONG(entropy)
|
||||
web2py_validate_entropy = $.web2py.validate_entropy;
|
||||
//needed for crud.search and SQLFORM.grid's search
|
||||
web2py_ajax_fields = $.web2py.ajax_fields;
|
||||
//used for LOAD(ajax=False)
|
||||
web2py_trap_form = $.web2py.trap_form;
|
||||
|
||||
/*undocumented - rare*/
|
||||
popup = $.web2py.popup;
|
||||
collapse = $.web2py.collapse;
|
||||
fade = $.web2py.fade;
|
||||
|
||||
/* internals - shouldn't be needed
|
||||
|
||||
web2py_ajax_init = $.web2py.ajax_init;
|
||||
web2py_event_handlers = $.web2py.event_handlers;
|
||||
|
||||
web2py_trap_link = $.web2py.trap_link;
|
||||
web2py_calc_entropy = $.web2py.calc_entropy;
|
||||
*/
|
||||
/* compatibility code - end*/
|
||||
|
||||
@@ -1,242 +1,653 @@
|
||||
function popup(url) {
|
||||
newwindow=window.open(url,'name','height=400,width=600');
|
||||
if (window.focus) newwindow.focus();
|
||||
return false;
|
||||
}
|
||||
function collapse(id) { jQuery('#'+id).slideToggle(); }
|
||||
function fade(id,value) { if(value>0) jQuery('#'+id).hide().fadeIn('slow'); else jQuery('#'+id).show().fadeOut('slow'); }
|
||||
function ajax(u,s,t) {
|
||||
query = '';
|
||||
if (typeof s == "string") {
|
||||
d = jQuery(s).serialize();
|
||||
if(d){ query = d; }
|
||||
} else {
|
||||
(function ($, undefined) {
|
||||
/*
|
||||
* Unobtrusive scripting adapter for jQuery, largely taken from
|
||||
* the wonderful https://github.com/rails/jquery-ujs
|
||||
*
|
||||
*
|
||||
* Released under the MIT license
|
||||
*
|
||||
*/
|
||||
|
||||
String.prototype.reverse = function () {
|
||||
return this.split('').reverse().join('');
|
||||
};
|
||||
var web2py;
|
||||
|
||||
$.web2py = web2py = {
|
||||
|
||||
popup: function (url) {
|
||||
newwindow = window.open(url, 'name', 'height=400,width=600');
|
||||
if(window.focus) newwindow.focus();
|
||||
return false;
|
||||
},
|
||||
collapse: function (id) {
|
||||
$('#' + id).slideToggle();
|
||||
},
|
||||
fade: function (id, value) {
|
||||
if(value > 0) $('#' + id).hide().fadeIn('slow');
|
||||
else $('#' + id).show().fadeOut('slow');
|
||||
},
|
||||
ajax: function (u, s, t) {
|
||||
query = '';
|
||||
if(typeof s == "string") {
|
||||
d = $(s).serialize();
|
||||
if(d) {
|
||||
query = d;
|
||||
}
|
||||
} else {
|
||||
pcs = [];
|
||||
if (s != null && s != undefined) for(i=0; i<s.length; i++) {
|
||||
q = jQuery("[name="+s[i]+"]").serialize();
|
||||
if(q){pcs.push(q);}
|
||||
if(s != null && s != undefined) for(i = 0; i < s.length; i++) {
|
||||
q = $("[name=" + s[i] + "]").serialize();
|
||||
if(q) {
|
||||
pcs.push(q);
|
||||
}
|
||||
}
|
||||
if(pcs.length > 0) {
|
||||
query = pcs.join("&");
|
||||
}
|
||||
if (pcs.length>0){query = pcs.join("&");}
|
||||
}
|
||||
jQuery.ajax({type: "POST", url: u, data: query, success: function(msg) { if(t) { if(t==':eval') eval(msg); else if(typeof t=='string') jQuery("#"+t).html(msg); else t(msg); } } });
|
||||
}
|
||||
|
||||
String.prototype.reverse = function () { return this.split('').reverse().join('');};
|
||||
function web2py_ajax_fields(target) {
|
||||
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
||||
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
||||
jQuery("input.date",target).each(function() {Calendar.setup({inputField:this, ifFormat:date_format, showsTime:false });});
|
||||
jQuery("input.datetime",target).each(function() {Calendar.setup({inputField:this, ifFormat:datetime_format, showsTime: true, timeFormat: "24" });});
|
||||
jQuery("input.time",target).each(function(){jQuery(this).timeEntry();});
|
||||
|
||||
};
|
||||
|
||||
function web2py_ajax_init(target) {
|
||||
jQuery('.hidden', target).hide();
|
||||
jQuery('.error', target).hide().slideDown('slow');
|
||||
web2py_ajax_fields(target);
|
||||
web2py_show_if(target);
|
||||
};
|
||||
|
||||
function web2py_event_handlers() {
|
||||
var doc = jQuery(document)
|
||||
doc.on('click', '.flash', function(e){var t=jQuery(this); if(t.css('top')=='0px') t.slideUp('slow'); else t.fadeOut(); e.preventDefault();});
|
||||
doc.on('keyup', 'input.integer', function(){this.value=this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g,'').reverse();});
|
||||
doc.on('keyup', 'input.double, input.decimal', function(){this.value=this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g,'').reverse();});
|
||||
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
|
||||
doc.on('click', "input[type='checkbox'].delete", function(){if(this.checked) if(!confirm(confirm_message)) this.checked=false;});
|
||||
|
||||
doc.ajaxSuccess(function(e, xhr) {
|
||||
var redirect=xhr.getResponseHeader('web2py-redirect-location');
|
||||
var command=xhr.getResponseHeader('web2py-component-command');
|
||||
var flash=xhr.getResponseHeader('web2py-component-flash');
|
||||
if (redirect !== null) {
|
||||
window.location = redirect;
|
||||
};
|
||||
if(command !== null){
|
||||
eval(decodeURIComponent(command));
|
||||
}
|
||||
if(flash) {
|
||||
jQuery('.flash')
|
||||
.html(decodeURIComponent(flash))
|
||||
.append('<span id="closeflash">×</span>')
|
||||
.slideDown();
|
||||
}
|
||||
});
|
||||
|
||||
doc.ajaxError(function(e, xhr, settings, exception) {
|
||||
doc.off('click', '.flash')
|
||||
switch(xhr.status){
|
||||
case 500:
|
||||
$('.flash').html(ajax_error_500).slideDown();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
jQuery(function() {
|
||||
var flash = jQuery('.flash');
|
||||
flash.hide();
|
||||
if(flash.html()) flash.append('<span id="closeflash">×</span>').slideDown();
|
||||
web2py_ajax_init(document);
|
||||
web2py_event_handlers();
|
||||
});
|
||||
|
||||
function web2py_trap_form(action,target) {
|
||||
jQuery('#'+target+' form').each(function(i){
|
||||
var form=jQuery(this);
|
||||
if(!form.hasClass('no_trap'))
|
||||
form.submit(function(e){
|
||||
jQuery('.flash').hide().html('');
|
||||
web2py_ajax_page('post',action,form.serialize(),target);
|
||||
e.preventDefault();
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: u,
|
||||
data: query,
|
||||
success: function (msg) {
|
||||
if(t) {
|
||||
if(t == ':eval') eval(msg);
|
||||
else if(typeof t == 'string') $("#" + t).html(msg);
|
||||
else t(msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function web2py_trap_link(target) {
|
||||
jQuery('#'+target+' a.w2p_trap').each(function(i){
|
||||
var link=jQuery(this);
|
||||
link.click(function(e) {
|
||||
jQuery('.flash').hide().html('');
|
||||
web2py_ajax_page('get',link.attr('href'),[],target);
|
||||
e.preventDefault();
|
||||
});
|
||||
},
|
||||
ajax_fields: function (target) {
|
||||
/*this attaches something to a newly loaded fragment/page
|
||||
* Ideally all events should be bound to the document, so we can avoid calling
|
||||
* this over and over... all will be bound to the document
|
||||
*/
|
||||
var date_format = (typeof w2p_ajax_date_format != 'undefined') ? w2p_ajax_date_format : "%Y-%m-%d";
|
||||
var datetime_format = (typeof w2p_ajax_datetime_format != 'undefined') ? w2p_ajax_datetime_format : "%Y-%m-%d %H:%M:%S";
|
||||
$("input.date", target).each(function () {
|
||||
Calendar.setup({
|
||||
inputField: this,
|
||||
ifFormat: date_format,
|
||||
showsTime: false
|
||||
});
|
||||
}
|
||||
});
|
||||
$("input.datetime", target).each(function () {
|
||||
Calendar.setup({
|
||||
inputField: this,
|
||||
ifFormat: datetime_format,
|
||||
showsTime: true,
|
||||
timeFormat: "24"
|
||||
});
|
||||
});
|
||||
$("input.time", target).each(function () {
|
||||
$(this).timeEntry();
|
||||
});
|
||||
/*adds btn class to buttons*/
|
||||
$('button', target).addClass('btn');
|
||||
$('form input[type="submit"], form input[type="button"]', target).addClass('btn');
|
||||
/*no more inline javascript for PasswordWidget*/
|
||||
$('input[type=password][data-w2p_entropy]', target).each(function () {
|
||||
web2py.validate_entropy($(this));
|
||||
});
|
||||
/*no more inline javascript for ListWidget*/
|
||||
$('ul.w2p_list', target).each(function () {
|
||||
function pe(ul, e) {
|
||||
var new_line = ml(ul);
|
||||
rel(ul);
|
||||
if($(e.target).parent().is(':visible')) {
|
||||
//make sure we didn't delete the element before we insert after
|
||||
new_line.insertAfter($(e.target).parent());
|
||||
} else {
|
||||
//the line we clicked on was deleted, just add to end of list
|
||||
new_line.appendTo(ul);
|
||||
}
|
||||
new_line.find(":text").focus();
|
||||
return false;
|
||||
}
|
||||
|
||||
function web2py_ajax_page(method, action, data, target) {
|
||||
jQuery.ajax({'type':method, 'url':action, 'data':data,
|
||||
'beforeSend':function(xhr) {
|
||||
xhr.setRequestHeader('web2py-component-location', document.location);
|
||||
xhr.setRequestHeader('web2py-component-element', target);},
|
||||
'complete':function(xhr,text){
|
||||
var html=xhr.responseText;
|
||||
var content=xhr.getResponseHeader('web2py-component-content');
|
||||
var t = jQuery('#'+target);
|
||||
if(content=='prepend') t.prepend(html);
|
||||
else if(content=='append') t.append(html);
|
||||
else if(content!='hide') t.html(html);
|
||||
web2py_trap_form(action,target);
|
||||
web2py_trap_link(target);
|
||||
web2py_ajax_init('#'+target);
|
||||
}
|
||||
});
|
||||
}
|
||||
function rl(ul, e) {
|
||||
if($(ul).children().length > 1) {
|
||||
//only remove if we have more than 1 item so the list is never empty
|
||||
$(e.target).parent().remove();
|
||||
}
|
||||
}
|
||||
|
||||
function web2py_component(action, target, timeout, times){
|
||||
jQuery(function(){
|
||||
var jelement = jQuery("#" + target);
|
||||
var element = jelement.get(0);
|
||||
var statement = "jQuery('#" + target + "').get(0).reload();";
|
||||
jelement.reload = function (){
|
||||
// Continue if times is Infinity or
|
||||
// the times limit is not reached
|
||||
if (element.reload_check()){
|
||||
web2py_ajax_page('get', action, null, target);} }; // reload
|
||||
// Method to check timing limit
|
||||
element.reload_check = function (){
|
||||
if (jelement.hasClass('w2p_component_stop')) {clearInterval(this.timing);return false;}
|
||||
if (this.reload_counter == Infinity){return true;}
|
||||
else {
|
||||
if (!isNaN(this.reload_counter)){
|
||||
this.reload_counter -= 1;
|
||||
if (this.reload_counter < 0){
|
||||
if (!this.run_once){
|
||||
clearInterval(this.timing);
|
||||
return false;
|
||||
}
|
||||
function ml(ul) {
|
||||
var line = $(ul).find("li:first").clone(true);
|
||||
line.find(':text').val('');
|
||||
return line;
|
||||
}
|
||||
|
||||
function rel(ul) {
|
||||
$(ul).find("li").each(function () {
|
||||
var trimmed = $.trim($(this.firstChild).val());
|
||||
if(trimmed == '') $(this).remove();
|
||||
else $(this.firstChild).val(trimmed);
|
||||
});
|
||||
}
|
||||
var ul = this;
|
||||
$(ul).find(":text").after('<a href="#">+</a> <a href="#">-</a>').keypress(function (e) {
|
||||
return(e.which == 13) ? pe(ul, e) : true;
|
||||
}).next().click(function (e) {
|
||||
pe(ul, e);
|
||||
e.preventDefault();
|
||||
}).next().click(function (e) {
|
||||
rl(ul, e);
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
},
|
||||
ajax_init: function (target) {
|
||||
$('.hidden', target).hide();
|
||||
web2py.manage_errors(target);
|
||||
web2py.ajax_fields(target);
|
||||
web2py.show_if_handler(target);
|
||||
web2py.component_handler(target);
|
||||
},
|
||||
//manage errors in forms
|
||||
manage_errors: function(target) {
|
||||
$('.error', target).hide().slideDown('slow');
|
||||
//$('.error', target).hide().fadeIn('slow');
|
||||
},
|
||||
event_handlers: function () {
|
||||
/* This is called once for page
|
||||
* Ideally it should bound all the things that are needed
|
||||
*/
|
||||
var doc = $(document);
|
||||
doc.on('click', '.flash', function (e) {
|
||||
var t = $(this);
|
||||
if(t.css('top') == '0px') t.slideUp('slow');
|
||||
else t.fadeOut();
|
||||
//if I want to display a clickable something
|
||||
//inside flash, I should not be prevented to follow it
|
||||
//e.preventDefault();
|
||||
});
|
||||
doc.on('keyup', 'input.integer', function () {
|
||||
this.value = this.value.reverse().replace(/[^0-9\-]|\-(?=.)/g, '').reverse();
|
||||
});
|
||||
doc.on('keyup', 'input.double, input.decimal', function () {
|
||||
this.value = this.value.reverse().replace(/[^0-9\-\.,]|[\-](?=.)|[\.,](?=[0-9]*[\.,])/g, '').reverse();
|
||||
});
|
||||
var confirm_message = (typeof w2p_ajax_confirm_message != 'undefined') ? w2p_ajax_confirm_message : "Are you sure you want to delete this object?";
|
||||
doc.on('click', "input[type='checkbox'].delete", function () {
|
||||
if(this.checked) if(!web2py.confirm(confirm_message)) this.checked = false;
|
||||
});
|
||||
|
||||
doc.ajaxSuccess(function (e, xhr) {
|
||||
var redirect = xhr.getResponseHeader('web2py-redirect-location');
|
||||
var command = xhr.getResponseHeader('web2py-component-command');
|
||||
var flash = xhr.getResponseHeader('web2py-component-flash');
|
||||
if(redirect !== null) {
|
||||
window.location = redirect;
|
||||
};
|
||||
if(command !== null) {
|
||||
eval(decodeURIComponent(command));
|
||||
}
|
||||
if(flash) {
|
||||
web2py.flash(decodeURIComponent(flash))
|
||||
}
|
||||
});
|
||||
|
||||
doc.ajaxError(function (e, xhr, settings, exception) {
|
||||
//personally I don't like it.
|
||||
//if there's an error it it flashed and can be removed
|
||||
//as any other message
|
||||
//doc.off('click', '.flash')
|
||||
switch(xhr.status) {
|
||||
case 500:
|
||||
web2py.flash(ajax_error_500);
|
||||
}
|
||||
});
|
||||
|
||||
},
|
||||
trap_form: function (action, target) {
|
||||
$('#' + target + ' form').each(function (i) {
|
||||
var form = $(this);
|
||||
form.attr('data-w2p_target', target);
|
||||
if(!form.hasClass('no_trap')) {
|
||||
//should be there by default ?
|
||||
form.find('input[type=submit]').attr('data-w2p_disable_with', 'Working...');
|
||||
form.submit(function (e) {
|
||||
web2py.hide_flash();
|
||||
web2py.ajax_page('post', action, form.serialize(), target, form);
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
trap_link: function (target) {
|
||||
$('#' + target + ' a.w2p_trap').each(function (i) {
|
||||
var link = $(this);
|
||||
link.click(function (e) {
|
||||
web2py.hide_flash();
|
||||
web2py.ajax_page('get', link.attr('href'), [], target);
|
||||
e.preventDefault();
|
||||
});
|
||||
});
|
||||
},
|
||||
ajax_page: function (method, action, data, target, element) {
|
||||
//element is a new parameter, but should be put be put in front
|
||||
if(element == undefined) element = $(document);
|
||||
if(web2py.fire(element, 'ajax:before')) { //test a usecase, should stop here if returns false
|
||||
$.ajax({
|
||||
'type': method,
|
||||
'url': action,
|
||||
'data': data,
|
||||
'beforeSend': function (xhr, settings) {
|
||||
//added
|
||||
xhr.setRequestHeader('web2py-component-location', document.location);
|
||||
xhr.setRequestHeader('web2py-component-element', target);
|
||||
return web2py.fire(element, 'ajax:beforeSend', [xhr, settings]); //test a usecase, should stop here if returns false
|
||||
},
|
||||
//added
|
||||
'success': function (data, status, xhr) {
|
||||
//bummer for form submissions....the element is not there after complete
|
||||
//because it gets replaced by the new response....
|
||||
element.trigger('ajax:success', [data, status, xhr]);
|
||||
},
|
||||
//added
|
||||
'error': function (xhr, status, error) {
|
||||
//bummer for form submissions....in addition to the element being not there after
|
||||
//complete because it gets replaced by the new response, standard form
|
||||
//handling just returns the same status code for good and bad
|
||||
//form submissions (i.e. that triggered a validator error)
|
||||
element.trigger('ajax:error', [xhr, status, error]);
|
||||
},
|
||||
'complete': function (xhr, status) {
|
||||
element.trigger('ajax:complete', [xhr, status]);
|
||||
var html = xhr.responseText;
|
||||
var content = xhr.getResponseHeader('web2py-component-content');
|
||||
var t = $('#' + target);
|
||||
if(content == 'prepend') t.prepend(html);
|
||||
else if(content == 'append') t.append(html);
|
||||
else if(content != 'hide') t.html(html);
|
||||
web2py.trap_form(action, target);
|
||||
web2py.trap_link(target);
|
||||
web2py.ajax_init('#' + target);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
component: function (action, target, timeout, times, el) {
|
||||
//element is a new parameter, but should be put in front
|
||||
$(function () {
|
||||
var jelement = $("#" + target);
|
||||
var element = jelement.get(0);
|
||||
var statement = "jQuery('#" + target + "').get(0).reload();";
|
||||
element.reload = function () {
|
||||
// Continue if times is Infinity or
|
||||
// the times limit is not reached
|
||||
if(element.reload_check()) {
|
||||
web2py.ajax_page('get', action, null, target, el);
|
||||
}
|
||||
}; // reload
|
||||
// Method to check timing limit
|
||||
element.reload_check = function () {
|
||||
if(jelement.hasClass('w2p_component_stop')) {
|
||||
clearInterval(this.timing);
|
||||
return false;
|
||||
}
|
||||
if(this.reload_counter == Infinity) {
|
||||
return true;
|
||||
} else {
|
||||
if(!isNaN(this.reload_counter)) {
|
||||
this.reload_counter -= 1;
|
||||
if(this.reload_counter < 0) {
|
||||
if(!this.run_once) {
|
||||
clearInterval(this.timing);
|
||||
return false;
|
||||
}
|
||||
else{return true;}
|
||||
} }
|
||||
return false;}; // reload check
|
||||
if (!isNaN(timeout)){
|
||||
element.timeout = timeout;
|
||||
element.reload_counter = times;
|
||||
if (times > 1){
|
||||
// Multiple or infinite reload
|
||||
// Run first iteration
|
||||
web2py_ajax_page('get', action, null, target);
|
||||
element.run_once = false;
|
||||
element.timing = setInterval(statement, timeout);
|
||||
element.reload_counter -= 1;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}; // reload check
|
||||
if(!isNaN(timeout)) {
|
||||
element.timeout = timeout;
|
||||
element.reload_counter = times;
|
||||
if(times > 1) {
|
||||
// Multiple or infinite reload
|
||||
// Run first iteration
|
||||
web2py.ajax_page('get', action, null, target, el);
|
||||
element.run_once = false;
|
||||
element.timing = setInterval(statement, timeout);
|
||||
element.reload_counter -= 1;
|
||||
} else if(times == 1) {
|
||||
// Run once with timeout
|
||||
element.run_once = true;
|
||||
element.setTimeout = setTimeout;
|
||||
element.timing = setTimeout(statement, timeout);
|
||||
}
|
||||
} else {
|
||||
// run once (no timeout specified)
|
||||
element.reload_counter = Infinity;
|
||||
web2py.ajax_page('get', action, null, target, el);
|
||||
}
|
||||
else if (times == 1) {
|
||||
// Run once with timeout
|
||||
element.run_once = true;
|
||||
element.setTimeout = setTimeout;
|
||||
element.timing = setTimeout(statement, timeout);
|
||||
});
|
||||
},
|
||||
calc_entropy: function (mystring) {
|
||||
//calculate a simple entropy for a given string
|
||||
var csets = new Array(
|
||||
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
'0123456789', '!@#$\%^&*()', '~`-_=+[]{}\|;:\'",.<>?/',
|
||||
'0123456789abcdefghijklmnopqrstuvwxyz');
|
||||
var score = 0,
|
||||
other = {}, seen = {}, lastset = null,
|
||||
mystringlist = mystring.split('');
|
||||
for(var i = 0; i < mystringlist.length; i++) { // classify this character
|
||||
var c = mystringlist[i],
|
||||
inset = 5;
|
||||
for(var j = 0; j < csets.length; j++)
|
||||
if(csets[j].indexOf(c) != -1) {
|
||||
inset = j;
|
||||
break;
|
||||
}
|
||||
//calculate effect of character on alphabet size
|
||||
if(!(inset in seen)) {
|
||||
seen[inset] = 1;
|
||||
score += csets[inset].length;
|
||||
} else if(!(c in other)) {
|
||||
score += 1;
|
||||
other[c] = 1;
|
||||
}
|
||||
} else {
|
||||
// run once (no timeout specified)
|
||||
element.reload_counter = Infinity;
|
||||
web2py_ajax_page('get', action, null, target);
|
||||
} }); }
|
||||
if(inset != lastset) {
|
||||
score += 1;
|
||||
lastset = inset;
|
||||
}
|
||||
}
|
||||
var entropy = mystring.length * Math.log(score) / 0.6931471805599453;
|
||||
return Math.round(entropy * 100) / 100
|
||||
},
|
||||
validate_entropy: function (myfield, req_entropy) {
|
||||
//added
|
||||
if(myfield.data('w2p_entropy') != undefined) req_entropy = myfield.data('w2p_entropy');
|
||||
var validator = function () {
|
||||
var v = (web2py.calc_entropy(myfield.val()) || 0) / req_entropy;
|
||||
var r = 0,
|
||||
g = 0,
|
||||
b = 0,
|
||||
rs = function (x) {
|
||||
return Math.round(x * 15).toString(16)
|
||||
};
|
||||
if(v <= 0.5) {
|
||||
r = 1.0;
|
||||
g = 2.0 * v;
|
||||
} else {
|
||||
r = (1.0 - 2.0 * (Math.max(v, 0) - 0.5));
|
||||
g = 1.0;
|
||||
}
|
||||
var color = '#' + rs(r) + rs(g) + rs(b);
|
||||
myfield.css('background-color', color);
|
||||
entropy_callback = myfield.data('entropy_callback');
|
||||
if(entropy_callback) entropy_callback(v);
|
||||
}
|
||||
if(!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator).addClass('entropy_check');
|
||||
},
|
||||
web2py_websocket: function (url, onmessage, onopen, onclose) {
|
||||
if("WebSocket" in window) {
|
||||
var ws = new WebSocket(url);
|
||||
ws.onopen = onopen ? onopen : (function () {});
|
||||
ws.onmessage = onmessage;
|
||||
ws.onclose = onclose ? onclose : (function () {});
|
||||
return true; // supported
|
||||
} else return false; // not supported
|
||||
},
|
||||
/* new from here */
|
||||
// Form input elements bound by jquery-ujs
|
||||
formInputClickSelector: 'input[type=submit], input[type=image], button[type=submit], button:not([type])',
|
||||
// Form input elements disabled during form submission
|
||||
disableSelector: 'input, button, textarea, select',
|
||||
// Form input elements re-enabled after form submission
|
||||
enableSelector: 'input:disabled, button:disabled, textarea:disabled, select:disabled',
|
||||
// Triggers an event on an element and returns false if the event result is false
|
||||
fire: function (obj, name, data) {
|
||||
var event = $.Event(name);
|
||||
obj.trigger(event, data);
|
||||
return event.result !== false;
|
||||
},
|
||||
// Helper function, needed to provide consistent behavior in IE
|
||||
stopEverything: function (e) {
|
||||
$(e.target).trigger('w2p:everythingStopped');
|
||||
e.stopImmediatePropagation();
|
||||
return false;
|
||||
},
|
||||
confirm: function (message) {
|
||||
return confirm(message);
|
||||
},
|
||||
// replace element's html with the 'data-disable-with' after storing original html
|
||||
// and prevent clicking on it
|
||||
disableElement: function (el) {
|
||||
el.addClass('disabled');
|
||||
var method = el.prop('type') == 'submit' ? 'val' : 'html';
|
||||
// store enabled state
|
||||
el.data('w2p:enable-with', el[method]);
|
||||
/* little addition by default*/
|
||||
if((el.data('w2p_disable_with') == 'default') || (el.data('w2p_disable_with') === undefined)) {
|
||||
el.data('w2p_disable_with', 'Working...');
|
||||
}
|
||||
// set to disabled state
|
||||
el[method](el.data('w2p_disable_with'));
|
||||
|
||||
function web2py_websocket(url,onmessage,onopen,onclose) {
|
||||
if ("WebSocket" in window) {
|
||||
var ws = new WebSocket(url);
|
||||
ws.onopen = onopen?onopen:(function(){});
|
||||
ws.onmessage = onmessage;
|
||||
ws.onclose = onclose?onclose:(function(){});
|
||||
return true; // supported
|
||||
} else return false; // not supported
|
||||
}
|
||||
el.bind('click.w2pDisable', function (e) { // prevent further clicking
|
||||
return web2py.stopEverything(e);
|
||||
});
|
||||
},
|
||||
|
||||
// restore element to its original state which was disabled by 'disableElement' above
|
||||
enableElement: function (el) {
|
||||
var method = el.prop('type') == 'submit' ? 'val' : 'html';
|
||||
if(el.data('w2p:enable-with') !== undefined) {
|
||||
// set to old enabled state
|
||||
el[method](el.data('w2p:enable-with'));
|
||||
el.removeData('w2p:enable-with'); // clean up cache
|
||||
}
|
||||
el.removeClass('disabled');
|
||||
el.unbind('click.w2pDisable'); // enable element
|
||||
},
|
||||
//convenience wrapper, internal use only
|
||||
simple_component: function (action, target, element) {
|
||||
web2py.component(action, target, 0, 1, element);
|
||||
},
|
||||
//helper for flash messages
|
||||
flash: function(message, status) {
|
||||
var flash = $('.flash');
|
||||
web2py.hide_flash();
|
||||
flash.html(message).addClass(status);
|
||||
if(flash.html()) flash.append('<span id="closeflash"> × </span>').slideDown();
|
||||
},
|
||||
hide_flash: function() {
|
||||
$('.flash').hide().html('');
|
||||
},
|
||||
show_if_handler: function(target) {
|
||||
var triggers = {};
|
||||
var show_if = function () {
|
||||
var t = $(this);
|
||||
var id = t.attr('id');
|
||||
t.attr('value', t.val());
|
||||
for(var k = 0; k < triggers[id].length; k++) {
|
||||
var dep = $('#' + triggers[id][k], target);
|
||||
var tr = $('#' + triggers[id][k] + '__row', target);
|
||||
if(t.is(dep.attr('data-show-if'))) tr.slideDown();
|
||||
else tr.hide();
|
||||
}
|
||||
};
|
||||
$('[data-show-trigger]', target).each(function () {
|
||||
var name = $(this).attr('data-show-trigger');
|
||||
if(!triggers[name]) triggers[name] = [];
|
||||
triggers[name].push($(this).attr('id'));
|
||||
});
|
||||
for(var name in triggers) {
|
||||
$('#' + name, target).change(show_if).keyup(show_if);
|
||||
show_if.call($('#' + name, target));
|
||||
};
|
||||
},
|
||||
component_handler : function (target) {
|
||||
$('div[data-w2p_remote]', target).each(function () {
|
||||
var remote, times, timeout, target;
|
||||
var el = $(this);
|
||||
remote = el.data('w2p_remote');
|
||||
times = el.data('w2p_times');
|
||||
timeout = el.data('w2p_timeout');
|
||||
target = el.attr('id');
|
||||
web2py.component(remote, target, timeout, times, $(this));
|
||||
}
|
||||
)
|
||||
},
|
||||
a_handler: function (el, e) {
|
||||
e.preventDefault();
|
||||
var method = el.data('w2p_method');
|
||||
var action = el.attr('href');
|
||||
var target = el.data('w2p_target');
|
||||
var confirm_message = el.data('w2p_confirm');
|
||||
|
||||
function web2py_calc_entropy(mystring) {
|
||||
//calculate a simple entropy for a given string
|
||||
var csets = new Array(
|
||||
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
||||
'0123456789', '!@#$\%^&*()', '~`-_=+[]{}\|;:\'",.<>?/',
|
||||
'0123456789abcdefghijklmnopqrstuvwxyz');
|
||||
var score = 0, other = {}, seen = {}, lastset = null, mystringlist = mystring.split('');
|
||||
for (var i=0;i<mystringlist.length;i++) { // classify this character
|
||||
var c = mystringlist[i], inset=5;
|
||||
for(var j = 0; j<csets.length; j++)
|
||||
if (csets[j].indexOf(c) != -1) {inset = j; break;}
|
||||
//calculate effect of character on alphabet size
|
||||
if(!(inset in seen)) {seen[inset] = 1;score += csets[inset].length;}
|
||||
else if (!(c in other)) {score += 1;other[c] = 1;}
|
||||
if (inset != lastset) {score += 1;lastset = inset;}
|
||||
var pre_call = el.data('w2p_pre_call');
|
||||
if(pre_call != undefined) {
|
||||
eval(pre_call);
|
||||
}
|
||||
if(confirm_message != undefined) {
|
||||
if(confirm_message == 'default') confirm_message = w2p_ajax_confirm_message || 'Are you sure you want to delete this object?';
|
||||
if(!web2py.confirm(confirm_message)) {
|
||||
web2py.stopEverything(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(target == undefined) {
|
||||
if(method == 'GET') {
|
||||
web2py.simple_component(action, el.attr('id'), el); //not working with original
|
||||
} else if(method == 'POST') {
|
||||
//should be web2py.ajax(action, [], ''); but it's too simple
|
||||
web2py.ajax_page('post', action, [], 'bogus', el); //fixme?
|
||||
}
|
||||
} else {
|
||||
if(method == 'GET') {
|
||||
web2py.simple_component(action, target, el);
|
||||
} else if(method == 'POST') {
|
||||
//should be web2py.ajax(action, [], target); but it's too simple
|
||||
web2py.ajax_page('post', action, [], target, el);
|
||||
}
|
||||
}
|
||||
/*this should happen only on ajaxsuccess
|
||||
* and should block subsequent clicks until ajaxcomplete
|
||||
* NB: introduce the first incompatibility because normally
|
||||
* the element would be removed in either case
|
||||
/* removal code moved to the ajax:success event - START
|
||||
if(toremove != undefined) {
|
||||
toremove = el.closest(toremove);
|
||||
if(!toremove.length) {
|
||||
//this enables removal of whatever selector if a closest is not found
|
||||
toremove = $(toremove);
|
||||
}
|
||||
toremove.remove();
|
||||
}
|
||||
/* removal code moved to the ajax:success event - END */
|
||||
},
|
||||
a_handlers: function () {
|
||||
var el = $(document);
|
||||
el.on('click', 'a[data-w2p_method]', function (e) {
|
||||
web2py.a_handler($(this), e);
|
||||
});
|
||||
/* removal of element should happen only on success */
|
||||
el.on('ajax:success', 'a[data-w2p_method][data-w2p_remove]', function (e) {
|
||||
var el = $(this);
|
||||
var toremove = el.data('w2p_remove');
|
||||
if(toremove != undefined) {
|
||||
toremove = el.closest(toremove);
|
||||
if(!toremove.length) {
|
||||
//this enables removal of whatever selector if a closest is not found
|
||||
toremove = $(toremove);
|
||||
}
|
||||
toremove.remove();
|
||||
}
|
||||
});
|
||||
el.on('ajax:beforeSend', 'a[data-w2p_method][data-w2p_disable_with]', function (e) {
|
||||
web2py.disableElement($(this));
|
||||
});
|
||||
/*re-enable click on completion*/
|
||||
el.on('ajax:complete', 'a[data-w2p_method][data-w2p_disable_with]', function (e) {
|
||||
web2py.enableElement($(this));
|
||||
});
|
||||
},
|
||||
/* Disables form elements:
|
||||
- Caches element value in 'ujs:enable-with' data store
|
||||
- Replaces element text with value of 'data-disable-with' attribute
|
||||
- Sets disabled property to true
|
||||
*/
|
||||
disableFormElements: function(form) {
|
||||
form.find(web2py.disableSelector).each(function() {
|
||||
var element = $(this), method = element.is('button') ? 'html' : 'val';
|
||||
var disable_with = element.data('w2p_disable_with');
|
||||
if (disable_with == undefined) {
|
||||
element.data('w2p_disable_with', element[method]())
|
||||
}
|
||||
element.data('w2p:enable-with', element[method]());
|
||||
element[method](element.data('w2p_disable_with'));
|
||||
element.prop('disabled', true);
|
||||
});
|
||||
},
|
||||
|
||||
/* Re-enables disabled form elements:
|
||||
- Replaces element text with cached value from 'ujs:enable-with' data store (created in `disableFormElements`)
|
||||
- Sets disabled property to false
|
||||
*/
|
||||
enableFormElements: function(form) {
|
||||
form.find(web2py.enableSelector).each(function() {
|
||||
var element = $(this), method = element.is('button') ? 'html' : 'val';
|
||||
if (element.data('w2p:enable-with')) element[method](element.data('w2p:enable-with'));
|
||||
element.prop('disabled', false);
|
||||
});
|
||||
},
|
||||
form_handlers: function() {
|
||||
var el = $(document);
|
||||
el.on('ajax:beforeSend', 'form[data-w2p_target]', function (e) {
|
||||
web2py.disableFormElements($(this));
|
||||
});
|
||||
el.on('ajax:complete', 'form[data-w2p_target]', function (e) {
|
||||
web2py.enableFormElements($(this));
|
||||
});
|
||||
}
|
||||
var entropy = mystring.length*Math.log(score)/0.6931471805599453;
|
||||
return Math.round(entropy*100)/100
|
||||
}
|
||||
}
|
||||
|
||||
function web2py_validate_entropy(myfield, req_entropy) {
|
||||
var validator = function () {
|
||||
var v = (web2py_calc_entropy(myfield.val())||0)/req_entropy;
|
||||
var r=0,g=0,b=0,rs=function(x){return Math.round(x*15).toString(16)};
|
||||
if(v<=0.5) {r=1.0; g=2.0*v;}
|
||||
else {r=(1.0-2.0*(Math.max(v,0)-0.5)); g=1.0;}
|
||||
var color = '#'+rs(r)+rs(g)+rs(b);
|
||||
myfield.css('background-color',color);
|
||||
entropy_callback = myfield.data('entropy_callback');
|
||||
if(entropy_callback) entropy_callback(v);
|
||||
}
|
||||
if(!myfield.hasClass('entropy_check')) myfield.on('keyup', validator).on('keydown', validator).addClass('entropy_check');
|
||||
}
|
||||
//end of functions
|
||||
//main hook
|
||||
$(function () {
|
||||
var flash = $('.flash');
|
||||
flash.hide();
|
||||
if(flash.html()) web2py.flash(flash.html());
|
||||
web2py.ajax_init(document);
|
||||
web2py.event_handlers();
|
||||
web2py.a_handlers();
|
||||
web2py.form_handlers();
|
||||
});
|
||||
|
||||
function web2py_show_if(target) {
|
||||
var triggers = {};
|
||||
var show_if = function () {
|
||||
var t = jQuery(this);
|
||||
var id = t.attr('id');
|
||||
t.attr('value', t.val());
|
||||
for(var k = 0; k < triggers[id].length; k++) {
|
||||
var dep = jQuery('#' + triggers[id][k], target);
|
||||
var tr = jQuery('#' + triggers[id][k] + '__row', target);
|
||||
if(t.is(dep.attr('data-show-if'))) tr.slideDown();
|
||||
else tr.hide();
|
||||
}
|
||||
};
|
||||
jQuery('[data-show-trigger]', target).each(function () {
|
||||
var name = jQuery(this).attr('data-show-trigger');
|
||||
if(!triggers[name]) triggers[name] = [];
|
||||
triggers[name].push(jQuery(this).attr('id'));
|
||||
});
|
||||
for(var name in triggers) {
|
||||
jQuery('#' + name, target).change(show_if).keyup(show_if);
|
||||
show_if.call(jQuery('#' + name, target));
|
||||
};
|
||||
}
|
||||
})(jQuery);
|
||||
|
||||
/* compatibility code - start */
|
||||
ajax = $.web2py.ajax;
|
||||
web2py_component = $.web2py.component;
|
||||
web2py_websocket = $.web2py.websocket;
|
||||
web2py_ajax_page = $.web2py.ajax_page;
|
||||
//needed for IS_STRONG(entropy)
|
||||
web2py_validate_entropy = $.web2py.validate_entropy;
|
||||
//needed for crud.search and SQLFORM.grid's search
|
||||
web2py_ajax_fields = $.web2py.ajax_fields;
|
||||
//used for LOAD(ajax=False)
|
||||
web2py_trap_form = $.web2py.trap_form;
|
||||
|
||||
/*undocumented - rare*/
|
||||
popup = $.web2py.popup;
|
||||
collapse = $.web2py.collapse;
|
||||
fade = $.web2py.fade;
|
||||
|
||||
/* internals - shouldn't be needed
|
||||
|
||||
web2py_ajax_init = $.web2py.ajax_init;
|
||||
web2py_event_handlers = $.web2py.event_handlers;
|
||||
|
||||
web2py_trap_link = $.web2py.trap_link;
|
||||
web2py_calc_entropy = $.web2py.calc_entropy;
|
||||
*/
|
||||
/* compatibility code - end*/
|
||||
|
||||
+10
-10
@@ -167,15 +167,15 @@ def LOAD(c=None, f='index', args=None, vars=None,
|
||||
elif timeout <= 0:
|
||||
raise ValueError(
|
||||
"Timeout argument must be greater than zero or None")
|
||||
statement = "web2py_component('%s','%s', %s, %s);" \
|
||||
statement = "$.web2py.component('%s','%s', %s, %s);" \
|
||||
% (url, target, timeout, times)
|
||||
attr['_data-w2p_timeout'] = timeout
|
||||
attr['_data-w2p_times'] = times
|
||||
else:
|
||||
statement = "web2py_component('%s','%s');" % (url, target)
|
||||
script = SCRIPT(statement, _type="text/javascript")
|
||||
if not content is None:
|
||||
return TAG[''](script, DIV(content, **attr))
|
||||
else:
|
||||
return TAG[''](script)
|
||||
statement = "$.web2py.component('%s','%s');" % (url, target)
|
||||
attr['_data-w2p_remote'] = url
|
||||
if not target is None:
|
||||
return DIV(content, **attr)
|
||||
|
||||
else:
|
||||
if not isinstance(args, (list, tuple)):
|
||||
@@ -226,7 +226,7 @@ def LOAD(c=None, f='index', args=None, vars=None,
|
||||
link = URL(request.application, c, f, r=request,
|
||||
args=args, vars=vars, extension=extension,
|
||||
user_signature=user_signature)
|
||||
js = "web2py_trap_form('%s','%s');" % (link, target)
|
||||
js = "$.web2py.trap_form('%s','%s');" % (link, target)
|
||||
script = js and SCRIPT(js, _type="text/javascript") or ''
|
||||
return TAG[''](DIV(XML(page), **attr), script)
|
||||
|
||||
@@ -254,7 +254,7 @@ class LoadFactory(object):
|
||||
url = url or html.URL(request.application, c, f, r=request,
|
||||
args=args, vars=vars, extension=extension,
|
||||
user_signature=user_signature)
|
||||
script = html.SCRIPT('web2py_component("%s","%s")' % (url, target),
|
||||
script = html.SCRIPT('$.web2py.component("%s","%s")' % (url, target),
|
||||
_type="text/javascript")
|
||||
return html.TAG[''](script, html.DIV(content, **attr))
|
||||
else:
|
||||
@@ -305,7 +305,7 @@ class LoadFactory(object):
|
||||
link = html.URL(request.application, c, f, r=request,
|
||||
args=args, vars=vars, extension=extension,
|
||||
user_signature=user_signature)
|
||||
js = "web2py_trap_form('%s','%s');" % (link, target)
|
||||
js = "$.web2py.trap_form('%s','%s');" % (link, target)
|
||||
script = js and html.SCRIPT(js, _type="text/javascript") or ''
|
||||
return html.TAG[''](html.DIV(html.XML(page), **attr), script)
|
||||
|
||||
|
||||
+50
-55
@@ -594,9 +594,9 @@ class ConnectionPool(object):
|
||||
if f is None:
|
||||
f = self.connector
|
||||
|
||||
if not hasattr(self, "driver") or self.driver is None:
|
||||
LOGGER.debug("Skipping connection since there's no driver")
|
||||
return
|
||||
# if not hasattr(self, "driver") or self.driver is None:
|
||||
# LOGGER.debug("Skipping connection since there's no driver")
|
||||
# return
|
||||
|
||||
if not self.pool_size:
|
||||
self.connection = f()
|
||||
@@ -644,6 +644,8 @@ class BaseAdapter(ConnectionPool):
|
||||
TRUE = 'T'
|
||||
FALSE = 'F'
|
||||
T_SEP = ' '
|
||||
QUOTE_TEMPLATE = '"%s"'
|
||||
|
||||
types = {
|
||||
'boolean': 'CHAR(1)',
|
||||
'string': 'CHAR(%(length)s)',
|
||||
@@ -1046,7 +1048,7 @@ class BaseAdapter(ConnectionPool):
|
||||
if self.dbengine in ('postgres',) and ftype.startswith('geometry'):
|
||||
geotype, parms = ftype[:-1].split('(')
|
||||
schema = parms.split(',')[0]
|
||||
query = [ "SELECT DropGeometryColumn ('%(schema)s', '%(table)s', '%(field)s');" %
|
||||
query = [ "SELECT DropGeometryColumn ('%(schema)s', '%(table)s', '%(field)s');" %
|
||||
dict(schema=schema, table=tablename, field=key,) ]
|
||||
elif self.dbengine in ('firebird',):
|
||||
query = ['ALTER TABLE %s DROP %s;' % (tablename, key)]
|
||||
@@ -1067,12 +1069,13 @@ class BaseAdapter(ConnectionPool):
|
||||
drop_expr = 'ALTER TABLE %s DROP %s;'
|
||||
else:
|
||||
drop_expr = 'ALTER TABLE %s DROP COLUMN %s;'
|
||||
query = ['ALTER TABLE %s ADD %s__tmp %s;' % (t, key, tt),
|
||||
'UPDATE %s SET %s__tmp=%s;' % (t, key, key),
|
||||
key_tmp = key + '__tmp'
|
||||
query = ['ALTER TABLE %s ADD %s %s;' % (t, key_tmp, tt),
|
||||
'UPDATE %s SET %s=%s;' % (t, key_tmp, key),
|
||||
drop_expr % (t, key),
|
||||
'ALTER TABLE %s ADD %s %s;' % (t, key, tt),
|
||||
'UPDATE %s SET %s=%s__tmp;' % (t, key, key),
|
||||
drop_expr % (t, key)]
|
||||
'UPDATE %s SET %s=%s;' % (t, key, key_tmp),
|
||||
drop_expr % (t, key_tmp)]
|
||||
metadata_change = True
|
||||
elif sql_fields[key]['type'] != sql_fields_old[key]['type']:
|
||||
sql_fields_current[key] = sql_fields[key]
|
||||
@@ -1097,7 +1100,7 @@ class BaseAdapter(ConnectionPool):
|
||||
db.commit()
|
||||
self.save_dbt(table,sql_fields_current)
|
||||
logfile.write('success!\n')
|
||||
|
||||
|
||||
elif metadata_change:
|
||||
self.save_dbt(table,sql_fields_current)
|
||||
|
||||
@@ -1255,7 +1258,7 @@ class BaseAdapter(ConnectionPool):
|
||||
return '(%s LIKE %s)' % (self.expand(first),
|
||||
self.expand('%'+second, 'string'))
|
||||
|
||||
def CONTAINS(self,first,second,case_sensitive=False):
|
||||
def CONTAINS(self,first,second,case_sensitive=False):
|
||||
if first.type in ('string','text', 'json'):
|
||||
if isinstance(second,Expression):
|
||||
second = Expression(None,self.CONCAT('%',Expression(
|
||||
@@ -1361,7 +1364,7 @@ class BaseAdapter(ConnectionPool):
|
||||
|
||||
def expand(self, expression, field_type=None):
|
||||
if isinstance(expression, Field):
|
||||
out = '%s.%s' % (expression.tablename, expression.name)
|
||||
out = '%s.%s' % (expression.table, expression.name)
|
||||
if field_type == 'string' and not expression.type in (
|
||||
'string','text','json','password'):
|
||||
out = 'CAST(%s AS %s)' % (out, self.types['text'])
|
||||
@@ -1448,6 +1451,7 @@ class BaseAdapter(ConnectionPool):
|
||||
sql_v = ','.join(['%s=%s' % (field.name,
|
||||
self.expand(value, field.type)) \
|
||||
for (field, value) in fields])
|
||||
tablename = "%s" % self.db[tablename]
|
||||
return 'UPDATE %s SET %s%s;' % (tablename, sql_v, sql_w)
|
||||
|
||||
def update(self, tablename, query, fields):
|
||||
@@ -2433,6 +2437,8 @@ class MySQLAdapter(BaseAdapter):
|
||||
'big-reference': 'BIGINT, INDEX %(index_name)s (%(field_name)s), FOREIGN KEY (%(field_name)s) REFERENCES %(foreign_key)s ON DELETE %(on_delete_action)s',
|
||||
}
|
||||
|
||||
QUOTE_TEMPLATE = "`%s`"
|
||||
|
||||
def varquote(self,name):
|
||||
return varquote_aux(name,'`%s`')
|
||||
|
||||
@@ -3082,6 +3088,8 @@ class MSSQLAdapter(BaseAdapter):
|
||||
drivers = ('pyodbc',)
|
||||
T_SEP = 'T'
|
||||
|
||||
QUOTE_TEMPLATE = "[%s]"
|
||||
|
||||
types = {
|
||||
'boolean': 'BIT',
|
||||
'string': 'VARCHAR(%(length)s)',
|
||||
@@ -6857,23 +6865,24 @@ class Row(object):
|
||||
this is only used to store a Row
|
||||
"""
|
||||
|
||||
def __init__(self,*args,**kwargs):
|
||||
self.__dict__.update(*args,**kwargs)
|
||||
__init__ = lambda self,*args,**kwargs: self.__dict__.update(*args,**kwargs)
|
||||
|
||||
def __getitem__(self, key):
|
||||
key=str(key)
|
||||
def __getitem__(self, k):
|
||||
key=str(k)
|
||||
_extra = getattr(self, '_extra', None)
|
||||
if _extra:
|
||||
return _extra.get(key)
|
||||
if v:
|
||||
return v
|
||||
m = REGEX_TABLE_DOT_FIELD.match(key)
|
||||
if key in self.get('_extra',{}):
|
||||
return self._extra[key]
|
||||
elif m:
|
||||
if m:
|
||||
try:
|
||||
return ogetattr(self, m.group(1))[m.group(2)]
|
||||
except (KeyError,AttributeError,TypeError):
|
||||
key = m.group(2)
|
||||
return ogetattr(self, key)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
setattr(self, str(key), value)
|
||||
__setitem__ = lambda self, key, value: setattr(self, str(key), value)
|
||||
|
||||
__delitem__ = object.__delattr__
|
||||
|
||||
@@ -6881,47 +6890,31 @@ class Row(object):
|
||||
|
||||
__call__ = __getitem__
|
||||
|
||||
def get(self,key,default=None):
|
||||
return self.__dict__.get(key,default)
|
||||
get = lambda self, key, default=None: self.__dict__.get(key,default)
|
||||
|
||||
def __contains__(self,key):
|
||||
return key in self.__dict__
|
||||
|
||||
has_key = __contains__
|
||||
has_key = __contains__ = lambda self, key: key in self.__dict__
|
||||
|
||||
def __nonzero__(self):
|
||||
return len(self.__dict__)>0
|
||||
__nonzero__ = lambda self: len(self.__dict__)>0
|
||||
|
||||
def update(self, *args, **kwargs):
|
||||
self.__dict__.update(*args, **kwargs)
|
||||
update = lambda self, *args, **kwargs: self.__dict__.update(*args, **kwargs)
|
||||
|
||||
def keys(self):
|
||||
return self.__dict__.keys()
|
||||
keys = lambda self: self.__dict__.keys()
|
||||
|
||||
def items(self):
|
||||
return self.__dict__.items()
|
||||
items = lambda self: self.__dict__.items()
|
||||
|
||||
def values(self):
|
||||
return self.__dict__.values()
|
||||
values = lambda self: self.__dict__.values()
|
||||
|
||||
def __iter__(self):
|
||||
return self.__dict__.__iter__()
|
||||
__iter__ = lambda self: self.__dict__.__iter__()
|
||||
|
||||
def iteritems(self):
|
||||
return self.__dict__.iteritems()
|
||||
iteritems = lambda self: self.__dict__.iteritems()
|
||||
|
||||
def __str__(self):
|
||||
### this could be made smarter
|
||||
return '<Row %s>' % self.as_dict()
|
||||
__str__ = __repr__ = lambda self: '<Row %s>' % self.as_dict()
|
||||
|
||||
def __repr__(self):
|
||||
return '<Row %s>' % self.as_dict()
|
||||
__int__ = lambda self: object.__getattribute__(self,'id')
|
||||
|
||||
def __int__(self):
|
||||
return object.__getattribute__(self,'id')
|
||||
__long__ = lambda self: long(object.__getattribute__(self,'id'))
|
||||
|
||||
def __long__(self):
|
||||
return long(object.__getattribute__(self,'id'))
|
||||
|
||||
def __eq__(self,other):
|
||||
try:
|
||||
@@ -8492,9 +8485,10 @@ class Table(object):
|
||||
|
||||
def __str__(self):
|
||||
if self._ot is not None:
|
||||
if 'Oracle' in str(type(self._db._adapter)): # <<< patch
|
||||
return '%s %s' % (self._ot, self._tablename) # <<< patch
|
||||
return '%s AS %s' % (self._ot, self._tablename)
|
||||
return self._db._adapter.QUOTE_TEMPLATE % self._ot
|
||||
#if 'Oracle' in str(type(self._db._adapter)): # <<< patch
|
||||
# return '%s %s' % (self._ot, self._tablename) # <<< patch
|
||||
#return '%s AS %s' % (self._ot, self._tablename)
|
||||
return self._tablename
|
||||
|
||||
def _drop(self, mode = ''):
|
||||
@@ -9959,7 +9953,7 @@ class Set(object):
|
||||
fields = table._listify(update_fields,update=True)
|
||||
if not fields:
|
||||
raise SyntaxError("No fields to update")
|
||||
ret = db._adapter.update(tablename,self.query,fields)
|
||||
ret = db._adapter.update("%s" % table,self.query,fields)
|
||||
ret and [f(self,update_fields) for f in table._after_update]
|
||||
return ret
|
||||
|
||||
@@ -9971,7 +9965,8 @@ class Set(object):
|
||||
table = self.db[tablename]
|
||||
fields = table._listify(update_fields,update=True)
|
||||
if not fields: raise SyntaxError("No fields to update")
|
||||
ret = self.db._adapter.update(tablename,self.query,fields)
|
||||
|
||||
ret = self.db._adapter.update("%s" % table,self.query,fields)
|
||||
return ret
|
||||
|
||||
def validate_and_update(self, **update_fields):
|
||||
@@ -10301,10 +10296,10 @@ class Rows(object):
|
||||
"""
|
||||
Takes an index and returns a copy of the indexed row with values
|
||||
transformed via the "represent" attributes of the associated fields.
|
||||
|
||||
|
||||
If no index is specified, a generator is returned for iteration
|
||||
over all the rows.
|
||||
|
||||
|
||||
fields -- a list of fields to transform (if None, all fields with
|
||||
"represent" attributes will be transformed).
|
||||
"""
|
||||
|
||||
@@ -83,7 +83,6 @@ class Request(Storage):
|
||||
|
||||
def __init__(self):
|
||||
Storage.__init__(self)
|
||||
self.wsgi = Storage() # hooks to environ and start_response
|
||||
self.env = Storage()
|
||||
self.cookies = Cookie.SimpleCookie()
|
||||
self.get_vars = Storage()
|
||||
|
||||
+19
-19
@@ -1479,30 +1479,30 @@ class A(DIV):
|
||||
def xml(self):
|
||||
if not self.components and self['_href']:
|
||||
self.append(self['_href'])
|
||||
if not self['_disable_with']:
|
||||
self['_data-w2p_disable_with'] = 'default'
|
||||
if self['delete']:
|
||||
d = "jQuery(this).closest('%s').remove();" % self['delete']
|
||||
else:
|
||||
d = ''
|
||||
self['_data-w2p_remove'] = self['delete']
|
||||
if self['target']:
|
||||
self['_data-w2p_target'] = self['target']
|
||||
if self['component']:
|
||||
self['_onclick'] = "web2py_component('%s','%s');%sreturn false;" % \
|
||||
(self['component'], self['target'] or '', d)
|
||||
self['_href'] = self['_href'] or '#null'
|
||||
self['_data-w2p_method'] = 'GET'
|
||||
self['_href'] = self['component']
|
||||
elif self['callback']:
|
||||
returnfalse = "var e = arguments[0] || window.event; e.cancelBubble=true; if (e.stopPropagation) {e.stopPropagation(); e.stopImmediatePropagation(); e.preventDefault();}"
|
||||
if d and not self['noconfirm']:
|
||||
self['_onclick'] = "if(confirm(w2p_ajax_confirm_message||'Are you sure you want to delete this object?')){ajax('%s',[],'%s');%s};%s" % \
|
||||
(self['callback'], self['target'] or '', d, returnfalse)
|
||||
else:
|
||||
self['_onclick'] = "ajax('%s',[],'%s');%sreturn false" % \
|
||||
(self['callback'], self['target'] or '', d)
|
||||
self['_href'] = self['_href'] or '#null'
|
||||
self['_data-w2p_method'] = 'POST'
|
||||
self['_href'] = self['callback']
|
||||
if self['delete'] and not self['noconfirm']:
|
||||
if not self['confirm']:
|
||||
self['_data-w2p_confirm'] = 'default'
|
||||
else:
|
||||
self['_data-w2p_confirm'] = self['confirm']
|
||||
elif self['cid']:
|
||||
pre = self['pre_call'] + ';' if self['pre_call'] else ''
|
||||
self['_onclick'] = '%sweb2py_component("%s","%s");%sreturn false;' % \
|
||||
(pre,self['_href'], self['cid'], d)
|
||||
self['_data-w2p_method'] = 'GET'
|
||||
self['_data-w2p_target'] = self['cid']
|
||||
if self['pre_call']:
|
||||
self['_data-w2p_pre_call'] = self['pre_call']
|
||||
return DIV.xml(self)
|
||||
|
||||
|
||||
class BUTTON(DIV):
|
||||
|
||||
tag = 'button'
|
||||
@@ -2481,7 +2481,7 @@ def test():
|
||||
|
||||
>>> from validators import *
|
||||
>>> print DIV(A('click me', _href=URL(a='a', c='b', f='c')), BR(), HR(), DIV(SPAN(\"World\"), _class='unknown')).xml()
|
||||
<div><a href=\"/a/b/c\">click me</a><br /><hr /><div class=\"unknown\"><span>World</span></div></div>
|
||||
<div><a data-w2p_disable_with="default" href="/a/b/c">click me</a><br /><hr /><div class=\"unknown\"><span>World</span></div></div>
|
||||
>>> print DIV(UL(\"doc\",\"cat\",\"mouse\")).xml()
|
||||
<div><ul><li>doc</li><li>cat</li><li>mouse</li></ul></div>
|
||||
>>> print DIV(UL(\"doc\", LI(\"cat\", _class='feline'), 18)).xml()
|
||||
|
||||
+53
-54
@@ -257,51 +257,55 @@ def serve_controller(request, response, session):
|
||||
raise HTTP(response.status, page, **response.headers)
|
||||
|
||||
|
||||
def start_response_aux(status, headers, exc_info, response=None):
|
||||
"""
|
||||
in controller you can use::
|
||||
|
||||
- request.wsgi.environ
|
||||
- request.wsgi.start_response
|
||||
|
||||
to call third party WSGI applications
|
||||
"""
|
||||
response.status = str(status).split(' ', 1)[0]
|
||||
response.headers = dict(headers)
|
||||
return lambda *args, **kargs: response.write(escape=False, *args, **kargs)
|
||||
|
||||
|
||||
def middleware_aux(request, response, *middleware_apps):
|
||||
"""
|
||||
In you controller use::
|
||||
|
||||
class LazyWSGI(object):
|
||||
def __init__(self, environ, request, response):
|
||||
self.wsgi_environ = environ
|
||||
self.request = request
|
||||
self.response = response
|
||||
@property
|
||||
def environ(self):
|
||||
if not hasattr(self,'_environ'):
|
||||
new_environ = self.wsgi_environ
|
||||
new_environ['wsgi.input'] = self.request.body
|
||||
new_environ['wsgi.version'] = 1
|
||||
self._environ = new_environ
|
||||
return self._environ
|
||||
def start_response(self,status='200', headers=[], exec_info=None):
|
||||
"""
|
||||
in controller you can use::
|
||||
|
||||
- request.wsgi.environ
|
||||
- request.wsgi.start_response
|
||||
|
||||
to call third party WSGI applications
|
||||
"""
|
||||
self.response.status = str(status).split(' ', 1)[0]
|
||||
self.response.headers = dict(headers)
|
||||
return lambda *args, **kargs: \
|
||||
self.response.write(escape=False, *args, **kargs)
|
||||
def middleware(self,*a):
|
||||
"""
|
||||
In you controller use::
|
||||
|
||||
@request.wsgi.middleware(middleware1, middleware2, ...)
|
||||
|
||||
to decorate actions with WSGI middleware. actions must return strings.
|
||||
uses a simulated environment so it may have weird behavior in some cases
|
||||
"""
|
||||
def middleware(f):
|
||||
def app(environ, start_response):
|
||||
data = f()
|
||||
start_response(response.status, response.headers.items())
|
||||
if isinstance(data, list):
|
||||
return data
|
||||
return [data]
|
||||
for item in middleware_apps:
|
||||
app = item(app)
|
||||
|
||||
def caller(app):
|
||||
wsgi = request.wsgi
|
||||
return app(wsgi.environ, wsgi.start_response)
|
||||
return lambda caller=caller, app=app: caller(app)
|
||||
return middleware
|
||||
|
||||
|
||||
def environ_aux(environ, request):
|
||||
new_environ = copy.copy(environ)
|
||||
new_environ['wsgi.input'] = request.body
|
||||
new_environ['wsgi.version'] = 1
|
||||
return new_environ
|
||||
|
||||
to decorate actions with WSGI middleware. actions must return strings.
|
||||
uses a simulated environment so it may have weird behavior in some cases
|
||||
"""
|
||||
def middleware(f):
|
||||
def app(environ, start_response):
|
||||
data = f()
|
||||
start_response(self.response.status,
|
||||
self.response.headers.items())
|
||||
if isinstance(data, list):
|
||||
return data
|
||||
return [data]
|
||||
for item in middleware_apps:
|
||||
app = item(app)
|
||||
def caller(app):
|
||||
return app(self.environ, self.start_response)
|
||||
return lambda caller=caller, app=app: caller(app)
|
||||
return middleware
|
||||
|
||||
ISLE25 = sys.version_info[1] <= 5
|
||||
|
||||
@@ -339,8 +343,9 @@ def parse_get_post_vars(request, environ):
|
||||
json_vars = {}
|
||||
pass
|
||||
# update vars and get_vars with what was posted as json
|
||||
request.get_vars.update(json_vars)
|
||||
request.vars.update(json_vars)
|
||||
if isinstance(json_vars,dict):
|
||||
request.get_vars.update(json_vars)
|
||||
request.vars.update(json_vars)
|
||||
|
||||
|
||||
# parse POST variables on POST, PUT, BOTH only in post_vars
|
||||
@@ -386,7 +391,7 @@ def parse_get_post_vars(request, environ):
|
||||
if len(pvalue):
|
||||
request.post_vars[key] = (len(pvalue) >
|
||||
1 and pvalue) or pvalue[0]
|
||||
if is_json:
|
||||
if is_json and isinstance(json_vars,dict):
|
||||
# update post_vars with what was posted as json
|
||||
request.post_vars.update(json_vars)
|
||||
|
||||
@@ -536,13 +541,7 @@ def wsgibase(environ, responder):
|
||||
# expose wsgi hooks for convenience
|
||||
# ##################################################
|
||||
|
||||
request.wsgi.environ = environ_aux(environ, request)
|
||||
request.wsgi.start_response = \
|
||||
lambda status='200', headers=[], \
|
||||
exec_info=None, response=response: \
|
||||
start_response_aux(status, headers, exec_info, response)
|
||||
request.wsgi.middleware = \
|
||||
lambda *a: middleware_aux(request, response, *a)
|
||||
request.wsgi = LazyWSGI(environ, request, response)
|
||||
|
||||
# ##################################################
|
||||
# load cookies
|
||||
|
||||
@@ -638,6 +638,8 @@ def regex_url_in(request, environ):
|
||||
if match.group('c') == 'static':
|
||||
application = match.group('a')
|
||||
version, filename = None, match.group('z')
|
||||
if not filename:
|
||||
raise HTTP(404)
|
||||
items = filename.split('/', 1)
|
||||
if regex_version.match(items[0]):
|
||||
version, filename = items
|
||||
|
||||
+3
-2
@@ -480,7 +480,8 @@ class Scheduler(MetaScheduler):
|
||||
Field('function_name',
|
||||
requires=IS_IN_SET(sorted(self.tasks.keys()))
|
||||
if self.tasks else DEFAULT),
|
||||
Field('uuid', requires=IS_NOT_IN_DB(db, 'scheduler_task.uuid'),
|
||||
Field('uuid', length=255,
|
||||
requires=IS_NOT_IN_DB(db, 'scheduler_task.uuid'),
|
||||
unique=True, default=web2py_uuid),
|
||||
Field('args', 'text', default='[]', requires=TYPE(list)),
|
||||
Field('vars', 'text', default='{}', requires=TYPE(dict)),
|
||||
@@ -521,7 +522,7 @@ class Scheduler(MetaScheduler):
|
||||
|
||||
db.define_table(
|
||||
'scheduler_worker',
|
||||
Field('worker_name', unique=True),
|
||||
Field('worker_name', length=255, unique=True),
|
||||
Field('first_heartbeat', 'datetime'),
|
||||
Field('last_heartbeat', 'datetime'),
|
||||
Field('status', requires=IS_IN_SET(WORKER_STATUS)),
|
||||
|
||||
+13
-58
@@ -86,8 +86,8 @@ def show_if(cond):
|
||||
if not cond:
|
||||
return None
|
||||
base = "%s_%s" % (cond.first.tablename, cond.first.name)
|
||||
if ((cond.op.__name__ == 'EQ' and cond.second == True) or
|
||||
(cond.op.__name__ == 'NE' and cond.second == False)):
|
||||
if ((cond.op.__name__ == 'EQ' and cond.second == True) or
|
||||
(cond.op.__name__ == 'NE' and cond.second == False)):
|
||||
return base,":checked"
|
||||
if ((cond.op.__name__ == 'EQ' and cond.second == False) or
|
||||
(cond.op.__name__ == 'NE' and cond.second == True)):
|
||||
@@ -97,7 +97,7 @@ def show_if(cond):
|
||||
if cond.op.__name__ == 'NE':
|
||||
return base,"[value!='%s']" % cond.second
|
||||
if cond.op.__name__ == 'CONTAINS':
|
||||
return base,"[value~='%s']" % cond.second
|
||||
return base,"[value~='%s']" % cond.second
|
||||
if cond.op.__name__ == 'BELONGS' and isinstance(cond.second,(list,tuple)):
|
||||
return base,','.join("[value='%s']" % (v) for v in cond.second)
|
||||
raise RuntimeError("Not Implemented Error")
|
||||
@@ -126,7 +126,7 @@ class FormWidget(object):
|
||||
_id='%s_%s' % (field.tablename, field.name),
|
||||
_class=cls._class or
|
||||
widget_class.match(str(field.type)).group(),
|
||||
_name=field.name,
|
||||
_name=field.name,
|
||||
requires=field.requires,
|
||||
)
|
||||
if getattr(field,'show_if',None):
|
||||
@@ -295,57 +295,15 @@ class ListWidget(StringWidget):
|
||||
_class = 'string'
|
||||
requires = field.requires if isinstance(
|
||||
field.requires, (IS_NOT_EMPTY, IS_LIST_OF)) else None
|
||||
attributes['_style'] = 'list-style:none'
|
||||
nvalue = value or ['']
|
||||
items = [LI(INPUT(_id=_id, _class=_class, _name=_name,
|
||||
value=v, hideerror=k < len(nvalue) - 1,
|
||||
requires=requires),
|
||||
**attributes) for (k, v) in enumerate(nvalue)]
|
||||
script = SCRIPT("""
|
||||
// from http://refactormycode.com/codes/694-expanding-input-list-using-jquery
|
||||
(function(){
|
||||
jQuery.fn.grow_input = function() {
|
||||
return this.each(function() {
|
||||
var ul = this;
|
||||
jQuery(ul).find(":text").after('<a href="javascript:void(0)">+</a> <a href="javascript:void(0)">-</a>').keypress(function (e) { return (e.which == 13) ? pe(ul, e) : true; }).next().click(function(e){ pe(ul, e) }).next().click(function(e){ rl(ul, e)});
|
||||
});
|
||||
};
|
||||
function pe(ul, e) {
|
||||
var new_line = ml(ul);
|
||||
rel(ul);
|
||||
if (jQuery(e.target).parent().is(':visible')) {
|
||||
//make sure we didn't delete the element before we insert after
|
||||
new_line.insertAfter(jQuery(e.target).parent());
|
||||
} else {
|
||||
//the line we clicked on was deleted, just add to end of list
|
||||
new_line.appendTo(ul);
|
||||
}
|
||||
new_line.find(":text").focus();
|
||||
return false;
|
||||
}
|
||||
function rl(ul, e) {
|
||||
if (jQuery(ul).children().length > 1) {
|
||||
//only remove if we have more than 1 item so the list is never empty
|
||||
jQuery(e.target).parent().remove();
|
||||
}
|
||||
}
|
||||
function ml(ul) {
|
||||
var line = jQuery(ul).find("li:first").clone(true);
|
||||
line.find(':text').val('');
|
||||
return line;
|
||||
}
|
||||
function rel(ul) {
|
||||
jQuery(ul).find("li").each(function() {
|
||||
var trimmed = jQuery.trim(jQuery(this.firstChild).val());
|
||||
if (trimmed=='') jQuery(this).remove(); else jQuery(this.firstChild).val(trimmed);
|
||||
});
|
||||
}
|
||||
})();
|
||||
jQuery(document).ready(function(){jQuery('#%s_grow_input').grow_input();});
|
||||
""" % _id)
|
||||
attributes['_id'] = _id + '_grow_input'
|
||||
attributes['_style'] = 'list-style:none'
|
||||
return TAG[''](UL(*items, **attributes), script)
|
||||
attributes['_class'] = 'w2p_list'
|
||||
return TAG[''](UL(*items, **attributes))
|
||||
|
||||
|
||||
class MultipleOptionsWidget(OptionsWidget):
|
||||
@@ -521,7 +479,6 @@ class PasswordWidget(FormWidget):
|
||||
_value=(value and cls.DEFAULT_PASSWORD_DISPLAY) or '',
|
||||
)
|
||||
attr = cls._attributes(field, default, **attributes)
|
||||
output = CAT(INPUT(**attr))
|
||||
|
||||
# deal with entropy check!
|
||||
requires = field.requires
|
||||
@@ -529,10 +486,9 @@ class PasswordWidget(FormWidget):
|
||||
requires = [requires]
|
||||
is_strong = [r for r in requires if isinstance(r, IS_STRONG)]
|
||||
if is_strong:
|
||||
output.append(SCRIPT("web2py_validate_entropy(jQuery('#%s'),%s);" % (
|
||||
attr['_id'], is_strong[0].entropy
|
||||
if is_strong[0].entropy else "null")))
|
||||
attr['_data-w2p_entropy'] = is_strong[0].entropy if is_strong[0].entropy else "null"
|
||||
# end entropy check
|
||||
output = INPUT(**attr)
|
||||
return output
|
||||
|
||||
|
||||
@@ -651,7 +607,7 @@ class AutocompleteWidget(object):
|
||||
self.help_fields = help_fields or []
|
||||
self.help_string = help_string
|
||||
if self.help_fields and not self.help_string:
|
||||
self.help_string = ' '.join('%%(%s)s'%f.name
|
||||
self.help_string = ' '.join('%%(%s)s'%f.name
|
||||
for f in self.help_fields)
|
||||
|
||||
self.request = request
|
||||
@@ -1484,7 +1440,7 @@ class SQLFORM(FORM):
|
||||
continue
|
||||
else:
|
||||
f = os.path.join(
|
||||
current.request.folder,
|
||||
current.request.folder,
|
||||
os.path.normpath(f))
|
||||
source_file = open(f, 'rb')
|
||||
original_filename = os.path.split(f)[1]
|
||||
@@ -2141,7 +2097,7 @@ class SQLFORM(FORM):
|
||||
else:
|
||||
rows = dbset.select(left=left, orderby=orderby,
|
||||
cacheable=True, *expcolumns)
|
||||
|
||||
|
||||
value = exportManager[export_type]
|
||||
clazz = value[0] if hasattr(value, '__getitem__') else value
|
||||
oExp = clazz(rows)
|
||||
@@ -2615,7 +2571,7 @@ class SQLFORM(FORM):
|
||||
except (KeyError, ValueError, TypeError):
|
||||
redirect(URL(args=table._tablename))
|
||||
if nargs == len(args) + 1:
|
||||
query = table._id != None
|
||||
query = table._db._adapter.id_query(table)
|
||||
|
||||
# filter out data info for displayed table
|
||||
if table._tablename in constraints:
|
||||
@@ -2694,7 +2650,7 @@ class SQLFORM(FORM):
|
||||
elif grid.view_form:
|
||||
header = T('View %(entity)s') % dict(
|
||||
entity=format(grid.view_form.table,
|
||||
grid.view_form.record))
|
||||
grid.view_form.record))
|
||||
if next:
|
||||
breadcrumbs.append(LI(
|
||||
A(T(header), _class=trap_class(),_href=url()),
|
||||
@@ -3136,4 +3092,3 @@ class ExporterJSON(ExportClass):
|
||||
return self.rows.as_json()
|
||||
else:
|
||||
return 'null'
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ class TestBareHelpers(unittest.TestCase):
|
||||
|
||||
def testA(self):
|
||||
self.assertEqual(A('<>', _a='1', _b='2').xml(),
|
||||
'<a a="1" b="2"><></a>')
|
||||
'<a a="1" b="2" data-w2p_disable_with="default"><></a>')
|
||||
|
||||
def testB(self):
|
||||
self.assertEqual(B('<>', _a='1', _b='2').xml(),
|
||||
@@ -209,8 +209,7 @@ class TestBareHelpers(unittest.TestCase):
|
||||
class TestData(unittest.TestCase):
|
||||
|
||||
def testAdata(self):
|
||||
self.assertEqual(A('<>', data=dict(abc='<def?asd>', cde='standard'), _a='1', _b='2').xml(),
|
||||
'<a a="1" b="2" data-abc="<def?asd>" data-cde="standard"><></a>')
|
||||
self.assertEqual(A('<>', data=dict(abc='<def?asd>', cde='standard'), _a='1', _b='2').xml(),'<a a="1" b="2" data-abc="<def?asd>" data-cde="standard" data-w2p_disable_with="default"><></a>')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
+7
-6
@@ -1545,7 +1545,7 @@ class Auth(object):
|
||||
settings.table_user_name, []) + signature_list
|
||||
if username or settings.cas_provider:
|
||||
is_unique_username = \
|
||||
[IS_MATCH('[\w\.\-]+'),
|
||||
[IS_MATCH('[\w\.\-]+', strict=True),
|
||||
IS_NOT_IN_DB(db, '%s.username' % settings.table_user_name)]
|
||||
if not settings.username_case_sensitive:
|
||||
is_unique_username.insert(1, IS_LOWER())
|
||||
@@ -1824,7 +1824,7 @@ class Auth(object):
|
||||
basic = current.request.env.http_authorization
|
||||
if basic_auth_realm:
|
||||
if callable(basic_auth_realm):
|
||||
basic_auth_realm = basic_auth_auth()
|
||||
basic_auth_realm = basic_auth_realm()
|
||||
elif isinstance(basic_auth_realm, (unicode, str)):
|
||||
basic_realm = unicode(basic_auth_realm)
|
||||
elif basic_auth_realm is True:
|
||||
@@ -5201,12 +5201,13 @@ class Wiki(object):
|
||||
return True
|
||||
|
||||
def can_see_menu(self):
|
||||
if self.settings.menu_groups is None:
|
||||
return True
|
||||
if self.auth.user:
|
||||
groups = self.auth.user_groups.values()
|
||||
if any(t in self.settings.menu_groups for t in groups):
|
||||
if self.settings.menu_groups is None:
|
||||
return True
|
||||
else:
|
||||
groups = self.auth.user_groups.values()
|
||||
if any(t in self.settings.menu_groups for t in groups):
|
||||
return True
|
||||
return False
|
||||
|
||||
### END POLICY
|
||||
|
||||
Reference in New Issue
Block a user