diff --git a/bower.json b/bower.json index 87d25aaa7..85d13f0b4 100644 --- a/bower.json +++ b/bower.json @@ -1,40 +1,40 @@ { "name": "invenio-grunt", "version": "0.1.0", "dependencies": { "bootstrap": "3.1.1", "jquery": "2.1.0", "font-awesome": "~4.0.3", "ckeditor": "latest" }, "devDependencies": { "typeahead.js": "0.10.1", "hogan": "3.0.0", "jquery-tokeninput": "*", "MathJax": "v2.1-latest", "jquery_jeditable": "http://invenio-software.org/download/jquery/v1.5/js/jquery.jeditable.mini.js", "jquery.treeview": "1.4.1", "jquery.tablesorter": "http://invenio-software.org/download/jquery/jquery.tablesorter.20111208.zip", "jqueryui": "1.10.4", "jquery.ui.timepicker": "http://invenio-software.org/download/jquery/jquery-ui-timepicker-addon-1.0.3.js", "jquery.multifile": "http://jquery-multifile-plugin.googlecode.com/svn/trunk/jquery.MultiFile.pack.js", "jquery.ajaxpager": "http://invenio-software.org/download/jquery/v1.5/js/jquery.ajaxPager.js", "jquery.bookmark": "http://invenio-software.org/download/jquery/jquery.bookmark.package-1.4.0.zip", "DataTables": "1_9", "jquery-flot": "*", "form": "https://raw.github.com/malsup/form/master/jquery.form.js", "jquery.hotkeys": "*", "uploadify": "*", "json2": "*", "prism": "gh-pages", "swfobject": "https://github.com/swfobject/swfobject/blob/master/swfobject/swfobject.js", "datatables-colvis": "*", - "typeahead.js-bootstrap": "https://raw.github.com/jharding/typeahead.js-bootstrap.css/master/typeahead.js-bootstrap.css", + "typeahead.js-bootstrap3.less": "0.2.2", "DataTables-Plugins": "https://github.com/DataTables/Plugins.git", "plupload": "*", "bootstrap-switch": "https://github.com/nostalgiaz/bootstrap-switch.git#3.0" }, "resolutions": { "jquery": "2.1.0" } } diff --git a/grunt/copy.js b/grunt/copy.js index 3effc2201..ce71c4459 100644 --- a/grunt/copy.js +++ b/grunt/copy.js @@ -1,241 +1,241 @@ /* * This file is part of Invenio. * Copyright (C) 2014 CERN. * * Invenio is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Invenio is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Invenio; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ 'use strict'; /*jshint laxcomma:true */ // FIXME? module.exports = { css: { expand: true, flatten: true, cwd: '<%= globalConfig.bower_path %>', src: ['bootstrap/dist/css/bootstrap*' ,'jquery-tokeninput/styles/token-input-facebook.css' ,'jquery-tokeninput/styles/token-input.css' ,'jquery.bookmark/jquery.bookmark.css' ,'datatables-colvis/media/css/ColVis.css' ,'DataTables-Plugins/integration/bootstrap/3/dataTables.bootstrap.css' ,'prism/prism.css'], dest: '<%= globalConfig.installation_path %>/css/' }, img: { expand: true, flatten: true, cwd: '<%= globalConfig.bower_path %>/', src: ['jquery.bookmark/bookmarks.png' ,'uploadify/uploadify*' ,'!uploadify/uploadify.php' ,'datatables-colvis/media/images/button.png' ,'DataTables-Plugins/integration/bootstrap/3/images/*.png'], dest: '<%= globalConfig.installation_path %>/img/' }, js: { expand: true, flatten: true, cwd: '<%= globalConfig.bower_path %>/', src: ['bootstrap/dist/js/bootstrap.js' ,'bootstrap/dist/js/bootstrap.min.js' ,'jquery/dist/jquery.min.js' ,'jquery/dist/jquery.min.map' ,'jquery-tokeninput/src/jquery.tokeninput.js' ,'jquery.bookmark/jquery.bookmark.min.js' ,'DataTables/media/js/jquery.dataTables.js' ,'jquery-flot/excanvas.min.js' ,'jquery-flot/jquery.flot.js' ,'jquery-flot/jquery.flot.selection.js' ,'jquery.hotkeys/jquery.hotkeys.js' ,'uploadify/jquery.uploadify.min.js' ,'json2/json2.js' ,'datatables-colvis/media/js/ColVis.js' ,'DataTables-Plugins/integration/bootstrap/3/dataTables.bootstrap.js' ,'prism/prism.js'], dest: '<%= globalConfig.installation_path %>/js/' }, fonts: { expand: true, flatten: true, cwd: '<%= globalConfig.bower_path %>/', src: ['bootstrap/dist/fonts/glyphicons-halflings-regular.*'], dest: '<%= globalConfig.installation_path %>/fonts/' }, typeahead: { expand: true, flatten: true, cwd: '<%= globalConfig.bower_path %>/', src: ['typeahead.js/dist/typeahead.bundle.min.js'], dest: '<%= globalConfig.installation_path %>/js/', rename: function(dest, src) { var res = src.replace(src.substring(0), 'typeahead.js'); return dest + res; } }, - typeaheadJSbootstrap: { + typeaheadBootstrap3Css: { expand: true, flatten: true, - cwd: '<%= globalConfig.bower_path %>/', - src: ['typeahead.js-bootstrap/index.css'], + cwd: '<%= globalConfig.bower_path %>/typeahead.js-bootstrap3.less', + src: ['typeahead.css'], dest: '<%= globalConfig.installation_path %>/css/', rename: function(dest, src) { var res = src.replace(src.substring(0), 'typeahead.js-bootstrap.css'); return dest + res; } }, hogan: { expand: true, flatten: true, cwd: '<%= globalConfig.bower_path %>/', src: ['hogan/web/builds/2.0.0/hogan-2.0.0.js'], dest: '<%= globalConfig.installation_path %>/js/', rename: function(dest, src) { return dest + src.substring(0, src.indexOf('-')) + '.js'; } }, jqueryUI: { expand: true, flatten: true, cwd: '<%= globalConfig.bower_path %>/jqueryui', src: ['**'], dest: '<%= globalConfig.installation_path %>/js/jqueryui' }, jqueryUISortable: { expand: true, flatten: true, cwd: '<%= globalConfig.bower_path %>/', src: ['jquery.ui/ui/jquery.ui.sortable.js'], dest: '<%= globalConfig.installation_path %>/js/' }, jqueryTimePicker: { expand: true, flatten: true, cwd: '<%= globalConfig.bower_path %>/', src: ['jquery.ui.timepicker/index.js'], dest: '<%= globalConfig.installation_path %>/js/', rename: function(dest, src) { var res = src.replace(src.substring(0), 'jquery-ui-timepicker-addon.js'); return dest + res; } }, MultiFile: { expand: true, flatten: true, cwd: '<%= globalConfig.bower_path %>/', src: ['jquery.multifile/index.js'], dest: '<%= globalConfig.installation_path %>/js/', rename: function(dest, src) { var res = src.replace(src.substring(0), 'jquery.MultiFile.pack.js'); return dest + res; } }, ajaxPager: { expand: true, flatten: true, cwd: '<%= globalConfig.bower_path %>/', src: ['jquery.ajaxpager/index.js'], dest: '<%= globalConfig.installation_path %>/js/', rename: function(dest, src) { var res = src.replace(src.substring(0), 'jquery.ajaxPager.js'); return dest + res; } }, form: { expand: true, flatten: true, cwd: '<%= globalConfig.bower_path %>/', src: ['form/index.js'], dest: '<%= globalConfig.installation_path %>/js/', rename: function(dest, src) { var res = src.replace(src.substring(0), 'jquery.form.js'); return dest + res; } }, swfobject: { expand: true, flatten: true, cwd: '<%= globalConfig.bower_path %>/', src: ['swfobject/index.js'], dest: '<%= globalConfig.installation_path %>/js/', rename: function(dest, src) { var res = src.replace(src.substring(0), 'swfobject.js'); return dest + res; } }, MathJax: { expand: true, cwd: '<%= globalConfig.bower_path %>/MathJax/', src: ['**'], dest: '<%= globalConfig.installation_path %>/MathJax/' }, ckeditor: { expand: true, cwd: '<%= globalConfig.bower_path %>/ckeditor/', src: ['**', '!**_samples/**', '!**_source/**', '!**php**', '!**_**', '!**pack**', '!**ckeditor.asp'], dest: '<%= globalConfig.installation_path %>/ckeditor/' }, jqueryTreeview: { expand: true, cwd: '<%= globalConfig.bower_path %>/jquery.treeview/', src: ['**'], dest: '<%= globalConfig.installation_path %>/js/jquery-treeview/' }, jqueryTableSorter: { expand: true, cwd: '<%= globalConfig.bower_path %>/jquery.tablesorter/', src: ['**'], dest: '<%= globalConfig.installation_path %>/js/tablesorter/' }, themesUI: { expand: true, cwd: '<%= globalConfig.bower_path %>/jquery.ui/themes/', src: ['**'], dest: '<%= globalConfig.installation_path %>/img/jquery-ui/themes' }, imagesUI: { expand: true, cwd: '<%= globalConfig.bower_path %>/jquery.ui/themes/base/images/', src: ['**'], dest: '<%= globalConfig.installation_path %>/img/images/' }, jeditable: { expand: true, cwd: '<%= globalConfig.bower_path %>/jquery_jeditable/', src: ['index.js'], dest: '<%= globalConfig.installation_path %>/js/', rename: function(dest, src) { if (src === 'index.js') { return dest + 'jquery.jeditable.mini.js'; } return dest + src; } }, plupload: { expand: true, cwd: '<%= globalConfig.bower_path %>/plupload/js', src: ['**'], dest: '<%= globalConfig.installation_path %>/plupload/' } }; diff --git a/invenio/base/templates/page_base.html b/invenio/base/templates/page_base.html index a181ef678..5da6aeccb 100644 --- a/invenio/base/templates/page_base.html +++ b/invenio/base/templates/page_base.html @@ -1,156 +1,154 @@ {# ## This file is part of Invenio. ## Copyright (C) 2012, 2013 CERN. ## ## Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## Invenio is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. #} {%- from "_macros.html" import flashed_messages, js_bundle, css_bundle with context -%} {# Global CSS #} {%- block global_css %} {%- css 'css/bootstrap.css', '00-invenio' -%} - {%- css 'css/typeahead.js-bootstrap.css', '00-invenio' -%} {%- css 'css/token-input.css', '00-invenio' -%} {%- css 'css/token-input-facebook.css', '00-invenio' -%} {%- css url_for('static', filename='css/base.css'), '00-invenio' -%} {%- css url_for('webtag.static', filename='css/tags/popover.css'), '00-invenio' -%} {%- if config.CFG_WEBSTYLE_TEMPLATE_SKIN != 'default' %} {%- css 'css/'+config.CFG_WEBSTYLE_TEMPLATE_SKIN+'.css', '00-invenio' -%} {%- endif %} {%- endblock global_css -%} {# Global Javascript files #} {%- block global_javascript -%} {%- js 'js/jquery.min.js', '00-invenio' -%} {%- js 'js/jquery.jeditable.mini.js', '10-invenio' -%} {%- js 'js/bootstrap.js', '10-invenio' -%} {%- js 'js/jquery.tokeninput.js', '10-invenio' -%} {%- js 'js/hogan.js', '10-invenio' -%} {%- js 'js/translate.js', '10-invenio' -%} - {%- js 'js/typeahead.js', '10-invenio' -%} {%- js 'js/invenio.js', '90-invenio' -%} {%- endblock global_javascript %} {%- block page -%} {%- if not no_pageheader -%} {%- block page_top -%} <!DOCTYPE html> <html{% if g.ln %} lang="{{ g.ln|safe }}"{% if is_language_rtl(g.ln) %} dir="rtl"{% endif %}{% endif %}> <head> {%- block head %} {%- block head_meta %} <meta charset="utf-8"> <title>{{ title+' - ' if title }}{{ config.CFG_SITE_NAME_INTL[g.ln] }}</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> {%- if description %}<meta name="description" content="{{ description }}" />{% endif %} {%- if keywords %}<meta name="keywords" content="{{ keywords }}" />{% endif %} {%- if config.get('CFG_GOOGLE_SITE_VERIFICATION', None) -%} {%- for google_id in config.CFG_GOOGLE_SITE_VERIFICATION %} <meta name="google-site-verification" content="{{google_id}}" /> {%- endfor -%} {%- endif -%} {%- endblock head_meta -%} {%- block head_links %} <link rel="author" href="mailto:{{ config.CFG_SITE_SUPPORT_EMAIL }}" /> <link rel="canonical" href="{{ canonical_url }}" /> {%- block head_links_langs %}{%- for alt_ln, alternate_url in alternate_urls.iteritems() %} <link rel="alternate" hreflang="{{ alt_ln }}" href="{{ alternate_url }}" /> {%- endfor %}{%- endblock %} <link rel="alternate" type="application/rss+xml" title="{{ config.CFG_SITE_NAME }} RSS" href="{{ url_for('rss') }}" /> <link rel="search" type="application/opensearchdescription+xml" href="{{ url_for('opensearchdescription') }}" title="{{ config.CFG_SITE_NAME }}" /> <link rel="unapi-server" type="application/xml" title="unAPI" href="{{ url_for('unapi') }}" /> {%- if linkbackTrackbackLink %}{{ linkbackTrackbackLink }}{%- endif %} <!-- Le HTML5 shim, for IE6-8 support of HTML5 elements --> <!--[if lt IE 9]> <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> <![endif]--> <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}"> {%- block head_apple_icons -%} {%- for size in [144, 114, 72, 57] -%} {%- set icon_name = 'apple-touch-icon-%d-precomposed.png'|format(size) %} <link rel="apple-touch-icon-precomposed" sizes="{{ size }}x{{ size }}" href="{{ url_for('static', filename=icon_name) }}"> {%- endfor -%} {%- endblock head_apple_icons -%} {%- endblock head_links %} {%- block header %}{{ metaheaderadd|safe }}{%- block metaheader %}{%- endblock metaheader -%}{%- endblock header -%} {{ css_bundle() }} {%- block _top_assets %}{% endblock _top_assets %} {%- block css %}{% endblock css %} {%- endblock head %} </head> <body{% if body_css_classes %} class="{{ body_css_classes|join(' ') }}"{% endif %}{% if g.ln %} lang="{{ g.ln.split('_', 1)[0]|safe }}"{% if rtl_direction %} {{ rtl_direction|safe }}{% endif %}{% endif %} itemscope itemtype="http://schema.org/WebPage"> {%- block body_start %}{% endblock body_start %} {%- block page_header -%} <div id="wrap"> <header> <!-- replaced page header --> {% block headerbox %} {% include 'header.html' %} {% endblock headerbox %} <!-- end replaced page header --> {% block breadcrumb %} {%- include 'breadcrumbs.html' -%} {% endblock breadcrumb %} {% block pageheaderadd %}{{ pageheaderadd|safe }}{% endblock pageheaderadd %} </header> {%- endblock page_header -%} {%- endblock page_top -%} {%- endif -%} {%- if not no_pagebody -%} {%- block page_body -%} <div class="container"> {% block title %} {% if title %} <div class="page-header"> <h1>{{ title }}</h1> </div> {% endif %} {% endblock title %} {{ flashed_messages() }} {% block body %} {{ body }} {% endblock body %} </div> {%- endblock page_body -%} {%- endif -%} {%- if not no_pagefooter -%} {%- block page_bottom -%} {%- block page_footer %} <div id="push"></div> </div>{# end wrap #} <footer> <div class="container"> {% block pagefooteradd %}{{ pagefooteradd|safe }}{% endblock pagefooteradd %} </div> <!-- replaced page footer --> {%- include 'footer.html' -%} </footer> {%- endblock page_footer %} {%- block _bottom_assets %} {{ js_bundle() }} {%- endblock _bottom_assets %} {%- block javascript %}{% endblock javascript %} {%- block body_end %}{% endblock body_end %} </body> </html> {%- endblock page_bottom -%} {%- endif -%} {%- endblock page -%} diff --git a/invenio/modules/deposit/autocomplete_utils.py b/invenio/modules/deposit/autocomplete_utils.py index 93a3d5e13..70adb3d6e 100644 --- a/invenio/modules/deposit/autocomplete_utils.py +++ b/invenio/modules/deposit/autocomplete_utils.py @@ -1,69 +1,69 @@ # -*- coding: utf-8 -*- ## ## This file is part of Invenio. ## Copyright (C) 2013 CERN. ## ## Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## Invenio is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. from invenio.utils.sherpa_romeo import SherpaRomeoSearch from invenio.utils.orcid import OrcidSearch def kb_autocomplete(name, mapper=None): """ Create a autocomplete function from knowledge base @param name: Name of knowledge base @param mapper: Function that will map an knowledge base entry to autocomplete entry. """ def inner(dummy_form, dummy_field, term, limit=50): from invenio.modules.knowledge.api import get_kb_mappings result = get_kb_mappings(name, '', term)[:limit] return map(mapper, result) if mapper is not None else result return inner -def sherpa_romeo_publishers(dummy_form, term, limit=50): +def sherpa_romeo_publishers(dummy_form, dummy_field, term, limit=50): if term: sherpa_romeo = SherpaRomeoSearch() publishers = sherpa_romeo.search_publisher(term) if publishers is None: return [] - return publishers + return map(lambda x: {'value': x}, publishers[:limit]) return [] -def sherpa_romeo_journals(dummy_form, term, limit=50): +def sherpa_romeo_journals(dummy_form, dummy_field, term, limit=50): """ Search SHERPA/RoMEO for journal name """ if term: # SherpaRomeoSearch doesnt' like unicode if isinstance(term, unicode): term = term.encode('utf8') s = SherpaRomeoSearch() journals = s.search_journal(term) if journals is not None: - return journals[:limit] + return map(lambda x: {'value': x}, journals[:limit]) return [] -def orcid_authors(dummy_form, term, limit=50): +def orcid_authors(dummy_form, dummy_field, term, limit=50): if term: orcid = OrcidSearch() orcid.search_authors(term) return orcid.get_authors_names() return [] diff --git a/invenio/modules/deposit/forms/article.py b/invenio/modules/deposit/forms/article.py index 488f2898d..cd85400e6 100644 --- a/invenio/modules/deposit/forms/article.py +++ b/invenio/modules/deposit/forms/article.py @@ -1,134 +1,134 @@ # -*- coding: utf-8 -*- ## ## This file is part of Invenio. ## Copyright (C) 2013 CERN. ## ## Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## Invenio is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA from wtforms.validators import Required from invenio.base.i18n import _ from invenio.modules.deposit.form import WebDepositForm from ..field_widgets import date_widget, plupload_widget, \ ExtendedListWidget, ListItemWidget, ckeditor_widget, TagInput, \ TagListWidget from invenio.modules.deposit import fields __all__ = ['ArticleForm'] def keywords_autocomplete(form, field, term, limit=50): - return ["Keyword 1", "Keyword 2"] + return [{'value': "Keyword 1"}, {'value': "Keyword 2"}] class AuthorForm(WebDepositForm): name = fields.TextField( placeholder="Family name, First name", widget_classes='form-control right-not-rounded', ) affiliation = fields.TextField( placeholder="Affiliation", widget_classes='form-control left-not-rounded', ) class ArticleForm(WebDepositForm): doi = fields.DOIField(label=_('DOI'), export_key='publication_info.DOI') publisher = fields.PublisherField(label=_('Publisher'), validators=[Required()], export_key='imprint.publisher_name') journal = fields.JournalField(label=_('Journal Title'), validators=[Required()]) issn = fields.ISSNField(label=_('ISSN'), export_key='issn') title = fields.TitleField(label=_('Document Title'), export_key='title.title') abstract = fields.AbstractField( label=_('Abstract'), export_key='abstract.summary', widget=ckeditor_widget, ) pagesnum = fields.PagesNumberField(label=_('Number of Pages')) languages = [("en", _("English")), ("fre", _("French")), ("ger", _("German")), ("dut", _("Dutch")), ("ita", _("Italian")), ("spa", _("Spanish")), ("por", _("Portuguese")), ("gre", _("Greek")), ("slo", _("Slovak")), ("cze", _("Czech")), ("hun", _("Hungarian")), ("pol", _("Polish")), ("nor", _("Norwegian")), ("swe", _("Swedish")), ("fin", _("Finnish")), ("rus", _("Russian"))] language = fields.LanguageField(label=_('Language'), choices=languages) date = fields.Date(label=_('Date of Document'), widget=date_widget, export_key='imprint.date') authors = fields.DynamicFieldList( fields.FormField( AuthorForm, widget=ExtendedListWidget( item_widget=ListItemWidget(with_label=False, class_="col-sm-6 col-xs-6 no-padding"), class_='collection-item list-unstyled', ), ), label='Authors', add_label='Add another author', icon='user', min_entries=1, export_key='authors' ) keywords = fields.DynamicFieldList( fields.TextField( placeholder="Start typing a keyword...", autocomplete=keywords_autocomplete, widget_classes="form-control", ), label='Keywords', add_label='Add another keyword', icon='tags', min_entries=1, export_key='keywords' ) notes = fields.NotesField(label=_('Notes'), export_key='comment') plupload_file = fields.FileUploadField(widget=plupload_widget, label="") """ Form Configuration variables """ _title = _('Submit an Article') _subtitle = 'Instructions: (i) Press "Save" to save your upload for '\ 'editing later, as many times you like. (ii) Upload or remove'\ ' extra files in the bottom of the form. (iii) When ready, '\ 'press "Submit" to finalize your upload.' _drafting = True # enable and disable drafting # Group fields in categories groups = [ ('Publisher/Journal', ['doi', 'publisher', 'journal', 'issn'], {'description': "Publisher and Journal fields are required.", 'indication': 'required'}), ('Basic Information', ['title', 'authors', 'abstract', 'pagesnum']), ('Other', ['language', 'date', 'keywords', 'notes']) ] diff --git a/invenio/modules/deposit/static/css/deposit/form.css b/invenio/modules/deposit/static/css/deposit/form.css new file mode 100644 index 000000000..909a0b425 --- /dev/null +++ b/invenio/modules/deposit/static/css/deposit/form.css @@ -0,0 +1,69 @@ +/* + * This file is part of Invenio. + * Copyright (C) 2014 CERN. + * + * Invenio is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * Invenio is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Invenio; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +/* + fix to keep datepicker widget above everything else, + particulary '.input-group .form-control' selector + which z-index equals 2 in bootstrap's css +*/ +#ui-datepicker-div { + z-index: 100 !important; +} + +span.ui-icon.ui-icon-circle-triangle-w { + color: transparent; cursor: pointer; +} +span.ui-icon.ui-icon-circle-triangle-e { + color: transparent; cursor: pointer; +} + +.l{ + size: 10px; +} + +.required:after { + color: red; + content:" *"; +} + +.rmlink { + cursor: pointer; +} +.sortlink { + cursor: move; + margin-left: 10px; +} +.empty-element { + display: none; +} +.sortlink:hover { + cursor: move; +} +.remove-element { + padding-left: 10px; +} +.field-list-element { + margin-bottom: 10px; +} +.field-list-element ul.inline { + margin: 0; +} +.tag { + cursor: move; +} \ No newline at end of file diff --git a/invenio/modules/deposit/static/js/deposit/form.js b/invenio/modules/deposit/static/js/deposit/form.js index 5fc6aa3fe..94b31a939 100644 --- a/invenio/modules/deposit/static/js/deposit/form.js +++ b/invenio/modules/deposit/static/js/deposit/form.js @@ -1,1458 +1,1444 @@ /* * This file is part of Invenio. * Copyright (C) 2013, 2014 CERN. * * Invenio is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * Invenio is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Invenio; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. */ var DEPOSIT_FORM = (function( $ ){ + var empty_cssclass = "empty-element"; + // // Helpers // function unique_id() { return Math.round(new Date().getTime() + (Math.random() * 100)); } /** * Get settings for performing an AJAX request with $.ajax * that will POST a JSON object to the given URL * * @param {} settings: A hash with the keys: url, data. */ function json_options(settings){ // Perform AJAX request with JSON data. return { url: settings.url, type: 'POST', cache: false, data: JSON.stringify(settings.data), contentType: "application/json; charset=utf-8", dataType: 'json' }; } function serialize_files(selector) { var ids, files, result; // Extract ids ids = $(selector).find('tr[id]').map(function(){ return $(this).attr('id');}); // Build search dict files = {}; $.each(uploader.files, function(idx, elem){ files[elem.id] = elem; }); // Build ordered list of server ids. result = []; $.each(ids, function(idx, id){ var file = files[id]; if(file !== undefined && file.status == 5) { result.push(file.server_id); } }); return result; } /** * Serialize a form */ function serialize_form(selector){ // Sync CKEditor before serializing for(var instance in CKEDITOR.instances){ var editor = CKEDITOR.instances[instance]; $('#'+instance).val(editor.getData()); } fields = $(selector).serializeArray(); if(uploader !== null){ fields.push({name: 'files', value: serialize_files('#filelist')}); } return serialize_object(fields); } /** * Serialize an array of name/value-pairs into a dictionary, taking * the name structure into account. */ function serialize_object(a){ var o = {}; $.each(a, function() { var sub_o = o; var names = this.name.split("-"); if(names.indexOf("__last_index__") != -1 || names.indexOf("__index__") != -1 || names.indexOf("__input__") != -1) { return; } for(var i = 0; i < names.length; i++){ var thisname = names[i]; var thisint = parseInt(thisname, 10); var thiskey = isNaN(thisint) ? thisname : thisint; if(i == names.length-1) { if (sub_o[thiskey] !== undefined) { if(!sub_o[thiskey].push) { sub_o[thiskey] = [sub_o[thiskey]]; } sub_o[thiskey].push(this.value || ''); } else { sub_o[thiskey] = this.value || ''; } } else { var nextname = names[i+1]; var nextint = parseInt(names[i+1], 10); if(sub_o[thiskey] === undefined){ if(isNaN(nextint)){ sub_o[thiskey] = {}; } else { sub_o[thiskey] = []; } } sub_o = sub_o[thiskey]; } } }); return o; } /** * jQuery plugin to serialize an DOM element */ $.fn.serialize_object = function(){ var inputs = $(this).find(':input'); var o = []; $.each(inputs, function() { if(this.name && !this.disabled && ((this.checked && this.type =='radio') || this.type != 'radio')) { o.push( { name: this.name, value: $(this).val() } ); } }); return serialize_object(o); }; /** * Create a new workflow */ function create_deposition(url){ var uuid; $.ajax({ url: url, async: false, type: 'POST', cache: false }).done(function(data) { uuid = data; }).fail(function() { uuid = null; }); return uuid; } /** */ function getBytesWithUnit(bytes){ if( isNaN( bytes ) ){ return ''; } var units = [' bytes', ' KB', ' MB', ' GB']; var amountOf2s = Math.floor( Math.log( +bytes )/Math.log(2) ); if( amountOf2s < 1 ){ amountOf2s = 0; } var i = Math.floor( amountOf2s / 10 ); bytes = +bytes / Math.pow( 2, 10*i ); // Rounds to 2 decimals places. bytes_to_fixed = bytes.toFixed(2); if( bytes.toString().length > bytes_to_fixed.toString().length ){ bytes = bytes_to_fixed; } return bytes + units[i]; } // // Response handlers // /** * Handle update of field message box. * * @return: True if message was set, False if no message was set. */ function handle_field_msg(name, data) { var has_error = false; if(!data) { return false; } var state = ''; if(data.state) { state = data.state; } if(data.messages && data.messages.length !== 0) { // if(!$('#state-' + name)){ // alert("Problem"); // } $('#state-' + name).html( tpl_field_message.render({ name: name, state: state, messages: data.messages }) ); ['info','warning','error','success'].map(function(s){ $("#state-group-" + name).removeClass(s); $("#state-" + name).removeClass('alert-'+s); if(s == state) { if(s == 'error') { has_error = true; } $("#state-group-" + name).addClass(state); $("#state-" + name).addClass('alert-'+state); } }); $('#state-' + name).show('fast'); return has_error; } else { clear_error(name); return has_error; } } /** */ function clear_error(name){ $('#state-' + name).hide(); $('#state-' + name).html(""); ['info','warning','error','success'].map(function(s){ $("#state-group-" + name).removeClass(s); $("#state-" + name).removeClass('alert-'+s); }); } /** * Update the value of a field to a new one. */ function handle_field_values(name, value) { if (name == 'files'){ $.each(value, function(i, file){ id = unique_id(); new_file = { id: id, name: file.name, size: file.size }; $('#filelist').append(tpl_file_entry.render({ id: id, filename: file.name, filesize: getBytesWithUnit(file.size) })); $('#filelist #' + id).show('fast'); }); $('#file-table').show('fast'); } else { clear_error(name); has_ckeditor = $('[name=' + name + ']').data('ckeditor'); if( has_ckeditor === 1) { if(CKEDITOR.instances[name].getData(value) != value) { CKEDITOR.instances[name].setData(value); } } else if (field_lists !== undefined && name in field_lists && value instanceof Array) { for(var i = 0; i < value.length; i++){ field_lists[name].update_element(value[i], i); } } else { if($('[name=' + name + ']').val() != value) { $('[name=' + name + ']').val(value); } } } } /** * Handle server response for multiple fields. */ function handle_response(data) { var errors = 0; if('messages' in data) { $.each(data.messages, function(name, data) { if(handle_field_msg(name, data)){ errors++; } }); } if('values' in data) { $.each(data.values, handle_field_values); } if('hidden_on' in data) { $.each(data.hidden_on, function(idx, field){ $('#state-group-'+field).hide("slow"); }); } if('hidden_off' in data) { $.each(data.hidden_off, function(idx, field){ $('#state-group-'+field).show("slow"); }); } if('disabled_on' in data) { $.each(data.disabled_on, function(idx, field){ $('#'+field).attr('disabled','disabled'); }); } if('disabled_off' in data) { $.each(data.disabled_off, function(idx, field){ $('#'+field).removeAttr('disabled'); }); } return errors; } /** * Set value of status indicator in form (e.g. saving, saved, ...) */ function set_status(tpl, ctx) { $('.status-indicator').show(); $('.status-indicator').html(tpl.render(ctx)); } function set_loader(selector, tpl, ctx) { $(selector).show(); $(selector).html(tpl.render(ctx)); } /** * Flash a message in the top. */ function _flash_message(ctx) { $('#flash-message').html(tpl_flash_message.render(ctx)); $('#flash-message').show('fast'); } /** * Save field value value */ function save_field(url, name, value) { request_data = {}; request_data[name] = value; save_data(url, request_data); } /** * Save field value value */ function save_data(url, request_data, flash_message, success_callback, failure_callback) { loader_selector = '#' + name + '-loader'; if(flash_message === undefined){ flash_message = false; } set_status(tpl_webdeposit_status_saving, request_data); set_loader(loader_selector, tpl_loader, request_data); $.ajax( json_options({url: url, data: request_data}) ).done(function(data) { var errors = handle_response(data); set_loader(loader_selector, tpl_loader_success, request_data); if(errors) { set_status(tpl_webdeposit_status_saved_with_errors, request_data); if(flash_message) { _flash_message({state:'warning', message: tpl_message_errors.render({})}); } if(failure_callback !== undefined){ failure_callback(); } } else { set_status(tpl_webdeposit_status_saved, request_data); if(flash_message) { _flash_message({state:'success', message: tpl_message_success.render({})}); } if(success_callback !== undefined){ success_callback(); } } }).fail(function() { set_status(tpl_webdeposit_status_error, request_data); set_loader(loader_selector, tpl_loader_success, request_data); }); } /** */ function check_status(url){ setInterval(function() { $.ajax({ type: 'GET', url: url }).done(function(data) { if (data.status == 1) location.reload(); }); }, 10000); } /** * Initialize PLUpload */ function init_plupload(max_size, selector, save_url, url, delete_url, get_file_url, db_files, dropbox_url, uuid, newdep_url, continue_url) { if($(selector).length === 0){ uploader = null; return; } var had_error = false; uploader = new plupload.Uploader({ // General settings runtimes : 'html5', url : url, max_file_size : max_size, chunk_size : '10mb', //unique_names : true, browse_button : 'pickfiles', drop_element : 'field-plupload_file' // Specify what files to browse for //filters : [ // {title : "Image files", extensions : "jpg,gif,png,tif"}, // {title : "Compressed files", extensions : "rar,zip,tar,gz"}, // {title : "PDF files", extensions : "pdf"} //] }); function init_uuid(){ if(uuid === null){ uuid = create_deposition(newdep_url); url = url.replace("-1", uuid); uploader.settings.url = url.replace("-1", uuid); delete_url = delete_url.replace("-1", uuid); get_file_url = get_file_url.replace("-1", uuid); dropbox_url = dropbox_url.replace("-1", uuid); continue_url = continue_url.replace("-1", uuid); } } queue_progress = new plupload.QueueProgress(); uploader.init(); function fake_file(file){ var plfile = new plupload.File({ id: file.id, name: file.name, size: file.size }); // Dont touch it! // For some reason the constructor doesn't initialize // the data members plfile.id = file.id; plfile.server_id = file.server_id || file.id; plfile.name = file.name; plfile.size = file.size; // loaded is set to 0 as a temporary fix plupload's bug in // calculating current upload speed. For checking if a file // has been uploaded, check file.status plfile.loaded = 0; //file.size; plfile.status = 5; //status = plupload.DONE plfile.percent = 100; return plfile; } $(function() { if (!jQuery.isEmptyObject(db_files)) { $('#file-table').show('slow'); $.each(db_files, function(i, file) { // Simulate a plupload file object var plfile = fake_file(file); uploader.files.push(plfile); $('#filelist').append(tpl_file_entry.render({ id: plfile.id, filename: plfile.name, filesize: getBytesWithUnit(plfile.size), download_url: get_file_url + "?file_id=" + plfile.id, removeable: true, completed: true, })); $('#filelist #' + plfile.id).show('fast'); $("#" + plfile.id + " .rmlink").on("click", function(event) { uploader.removeFile(plfile); }); }); } }); function init_button_states(){ $('#uploadfiles').addClass("disabled"); $('#stopupload').hide(); $('#uploadfiles').show(); $('#upload_speed').html(''); had_error = false; } function redirect(){ if(continue_url){ if( window.location != continue_url ){ window.location = continue_url; } } } function upload_dropbox_finished() { dropbox_files = []; redirect(); init_button_states(); } function upload_dropbox_file(i) { var file = dropbox_files[i]; $('#' + file.id + " .progress").hide(); $('#' + file.id + " .progress-bar").css('width', "100%"); $('#' + file.id + " .progress").addClass("progress-striped"); $('#' + file.id + " .progress").show(); $.ajax({ type: 'POST', url: dropbox_url, data: $.param({ name: file.name, size: file.size, url: file.url }), dataType: "json" }).done(function(data){ file.server_id = data['id']; $('#' + file.id + " .progress").removeClass("progress-striped"); $('#' + file.id + " .progress").hide(); $('#' + file.id + " .progress-bar").css('width', "100%"); $('#' + file.id + '_link').html(tpl_file_link.render({ filename: file.name, download_url: get_file_url + "?file_id=" + data['id'] })); var plfile = fake_file(file); uploader.files.push(plfile); i++; if(i < dropbox_files.length){ upload_dropbox_file(i); } else { upload_dropbox_finished(); } }); } function start_dropbox_upload() { init_uuid(); if(dropbox_files.length > 0) { upload_dropbox_file(0); } else { init_button_states(); } } $('#uploadfiles').click(function(e) { e.preventDefault(); $('#uploadfiles').addClass('disabled'); $('#uploadfiles').hide(); $('#stopupload').show(); if(uploader.files.length > 0){ uploader.start(); } else if (dropbox_files.length > 0) { start_dropbox_upload(); } }); $('#stopupload').click(function(d){ uploader.stop(); $('#stopupload').hide(); $('#uploadfiles').show(); $('#uploadfiles').removeClass('disabled'); $.each(uploader.files, function(i, file) { if (file.loaded < file.size) { $("#" + file.id + " .rmlink").show(); //$('#' + file.id + " .progress-bar").css('width', "0%"); } }); $('#upload_speed').html(''); uploader.total.reset(); }); uploader.bind('FilesRemoved', function(up, files) { $.each(files, function(i, file) { $('#filelist #' + file.id).hide('fast', function(){ $('#filelist #' + file.id).remove(); if($('#filelist').children().length === 0){ $('#uploadfiles').addClass("disabled"); } }); if (file.status === plupload.DONE) { //If file has been successfully uploaded $.ajax({ type: "POST", url: delete_url, data: $.param({ file_id: file.id }) }); } }); }); uploader.bind('UploadProgress', function(up, file) { $('#' + file.id + " .progress-bar").css('width', file.percent + "%"); upload_speed = getBytesWithUnit(up.total.bytesPerSec) + " per sec"; console.log("Progress " + file.name + " - " + file.percent); $('#upload_speed').html(upload_speed); up.total.reset(); }); uploader.bind('BeforeUpload', function(up, file) { init_uuid(); }); uploader.bind('UploadFile', function(up, file) { $('#' + file.id + " .rmlink").hide(); }); uploader.bind('FilesAdded', function(up, files) { var remove_files = []; $.each(up.files, function(i, file) { }); $(selector).removeClass("hide"); $('#uploadfiles').removeClass("disabled"); $('#file-table').show('slow'); up.total.reset(); var filename_already_exists = []; $.each(files, function(i, file) { // Check for existing file var removed = false; for(var j = 0; j<up.files.length; j++){ existing_file = up.files[j]; if(existing_file.id != file.id && file.name == existing_file.name){ filename_already_exists.push(file.name); up.removeFile(file); var removed = true; } } if(!removed){ $('#filelist').append(tpl_file_entry.render({ id: file.id, filename: file.name, filesize: getBytesWithUnit(file.size), removeable: true, progress: 0 })); $('#filelist #' + file.id).show('fast'); $('#' + file.id + ' .rmlink').on("click", function(event){ uploader.removeFile(file); }); } }); if(filename_already_exists.length > 0) { $('#upload-errors').hide(); $('#upload-errors').append('<div class="alert alert-warning"><a class="close" data-dismiss="alert" href="#">×</a><strong>Warning:</strong>' + filename_already_exists.join(", ") + " already exist.</div>"); $('#upload-errors').show('fast'); } }); uploader.bind('FileUploaded', function(up, file, responseObj) { try{ res_data = JSON.parse(responseObj.response); } catch (err) {} file.server_id = res_data.id; $('#' + file.id + " .progress").removeClass("progress-striped"); $('#' + file.id + " .progress-bar").css('width', "100%"); $('#' + file.id + ' .rmlink').show(); $('#' + file.id + " .progress").hide(); $('#' + file.id + '_link').html(tpl_file_link.render({ filename: file.name, download_url: get_file_url + "?file_id=" + res_data['id'] })); if (uploader.total.queued === 0) $('#stopupload').hide(); file.loaded = 0; $('#upload_speed').html(''); up.total.reset(); }); function error_message(err) { var error_messages = {}, message, http_errors; error_messages[plupload.FILE_EXTENSION_ERROR] = "the file extensions is not allowed."; error_messages[plupload.FILE_SIZE_ERROR] = "the file is too big."; error_messages[plupload.GENERIC_ERROR] = "an unknown error."; error_messages[plupload.IO_ERROR] = "problems reading the file on disk."; error_messages[plupload.SECURITY_ERROR] = "problems reading the file on disk."; message = error_messages[err.code]; if (message !== undefined) { return message; } if (err.code == plupload.HTTP_ERROR) { http_errors = {}; http_errors[401] = "an authentication error. Please login first."; http_errors[403] = "lack of permissions."; http_errors[404] = "a server error."; http_errors[500] = "a server error."; message = http_errors[err.status]; if (message !== undefined) { return message; } } return "an unknown error occurred"; } uploader.bind('Error', function(up, err) { had_error = true; var message = error_message(err); $('#upload-errors').hide(); if (err.file){ $('#' + err.file.id + " .progress").removeClass("progress-striped").addClass("progress-danger"); $('#upload-errors').append('<div class="alert alert-danger"><strong>Error:</strong> Could not upload ' + err.file.name +" due to " + message + "</div>"); } else { $('#upload-errors').append('<div class="alert alert-danger"><strong>Error:</strong> ' + message + "</div>"); } $('#upload-errors').show('fast'); $('#uploadfiles').addClass("disabled"); $('#stopupload').hide(); $('#uploadfiles').show(); up.refresh(); // Reposition Flash/Silverlight }); uploader.bind('UploadComplete', function(up, files) { if(dropbox_files.length > 0 && !had_error) { start_dropbox_upload(); } else { if(!had_error) { redirect(); } init_button_states(); } }); $("#filelist").sortable({ forcePlaceholderSize: true, forceHelperSizeType: true, handle: ".sortlink", start: function(event, ui) { $(ui.placeholder).show(); $(ui.placeholder).html("<td></td><td></td><td></td><td></td>"); $(ui.placeholder).css("visibility", ""); header_ths = $("#file-table thead th"); item_tds = $(ui.helper).find("td"); placeholder_tds = $(ui.placeholder).find("td"); for(var i = 0; i < header_ths.length; i++){ $(item_tds[i]).width($(header_ths[i]).width()); $(placeholder_tds[i]).width($(header_ths[i]).width()); } }, update: function(event, ui){ if(save_url) { save_field(save_url, 'files', serialize_files("#filelist")); } } }); $("#filelist").disableSelection(); } /** * Initialize save-button */ function init_save(url, selector, form_selector) { $(selector).click(function(e){ e.preventDefault(); save_data(url, serialize_form(form_selector), true); return false; }); } /** * Initialize submit-button */ function init_submit(url, selector, form_selector, dialog) { $(selector).click(function(e){ e.preventDefault(); submit(url, form_selector, dialog); }); } function submit(url, form_selector, dialog){ if(dialog !== undefined){ $(dialog).modal({ backdrop: 'static', keyboard: false, show: true, }); } save_data( url, serialize_form(form_selector), true, function success_callback() { window.location.reload(); }, function failure_callback() { if(dialog !== undefined){ $(dialog).modal('hide'); } } ); } /** * Initialize dynamic field lists */ var field_lists = {}; function init_field_lists(selector, url, autocomplete_selector, url_autocomplete) { function serialize_and_save(options) { // Save list on remove element, sorting and paste of list data = $('#'+options.prefix).serialize_object(); if($.isEmptyObject(data)){ data[options.prefix] = []; } save_data(url, data); } function install_handler(options, element) { // Install save handler when adding new elements $(element).find(":input").change( function() { save_field(url, this.name, this.value); }); $(element).find(autocomplete_selector).each(function (){ init_autocomplete(this, url, url_autocomplete); }); } var opts = { updated: serialize_and_save, removed: serialize_and_save, added: install_handler, pasted: serialize_and_save, }; $(selector).each(function(){ field_lists[$(this).attr('id')] = $(this).fieldlist(opts); }); } /** * Save and check field values for errors. */ function init_inputs(selector, url) { $(selector).change( function() { if(this.name.indexOf('__input__') == -1){ save_field(url, this.name, this.value); } }); } /** * Click form-button */ function init_buttons(selector, url) { $(selector).click( function() { save_field(url, this.name, true); return false; }); } /** * CKEditor initialization */ function init_ckeditor(selector, url) { $(selector).each(function(){ var options = $(this).data('ckeditorConfig'); if(options === undefined){ CKEDITOR.replace(this); } else { CKEDITOR.replace(this, options); } ckeditor = CKEDITOR.instances[$(this).attr('name')]; ckeditor.on('blur',function(e){ save_field(url, e.editor.name, e.editor.getData()); }); }); } /** * Autocomplete initialization */ function init_autocomplete(selector, save_url, url_template, handle_selection) { $(selector).each(function(){ var item = this; var url = url_template.replace("__FIELDNAME__", item.name); if(handle_selection === undefined){ handle_selection = typeahead_selection; } - if($(item).attr('type') != 'hidden') { - try { - init_bootstrap_typeahead(item, url, save_url, handle_selection); - } catch (err) { - init_typeaheadjs(item, url, save_url, handle_selection); - } + if($(item).parents('.' + empty_cssclass).length == 0) { + init_typeaheadjs(item, url, save_url, handle_selection); } }); } /** - * Bootstrap standard typeahead + * Twitter typeahead.js support for autocompletion */ - function init_bootstrap_typeahead(item, url, save_url, handle_selection) { + function init_typeaheadjs(item, url, save_url, handle_selection) { var autocomplete_request = null; function source(query, process) { - $(item).addClass('ui-autocomplete-loading'); - var typeahead = this; if(autocomplete_request !== null){ autocomplete_request.abort(); } + $(item).addClass('ui-autocomplete-loading'); autocomplete_request = $.ajax({ type: 'GET', url: url, data: $.param({term: query}) }).done(function(data) { process(data); $(item).removeClass('ui-autocomplete-loading'); }).fail(function(data) { - process([query]); $(item).removeClass('ui-autocomplete-loading'); }); } - function updater(datum) { - handle_selection(save_url, this.$element, datum, $(this.$element).attr('name')); - } - $(item).typeahead({ - source: source, - minLength: 5, - items: 50, - updater: updater + minLength: 1 + }, + { + source: source, + displayKey: 'value' }); - } - /** - * Twitter typeahead.js support for autocompletion - */ - function init_typeaheadjs(item, url, save_url, handle_selection) { - $(item).typeahead({ - name: item.name, - remote: url + "?term=%QUERY", - }); $(item).on('typeahead:selected', function(e, datum, name){ handle_selection(save_url, item, datum, name); }); } /** * Handle selection of an autocomplete option */ function typeahead_selection(save_url, item, datum, name) { if(typeof datum == 'string') { var value = datum; datum = {value: value, fields: {}}; datum.fields = value; } + if(datum.fields === undefined) { + datum.fields = datum.value; + } if(datum.fields !== undefined) { if(field_lists !== undefined){ var input_index = '__input__'; var item_id = $(item).attr('id'); var offset = item_id.indexOf(input_index); var field_list_name = item_id.slice(0,offset-1); if(field_lists[field_list_name] !== undefined){ field_lists[field_list_name].append_element(datum.fields, input_index); // Clear typeahead field try { $(item).typeahead('setQuery', ""); } catch (error) {} //Suppress error $(item).val(""); // Save list data = $('#'+field_list_name).serialize_object(); if($.isEmptyObject(data)){ data[options.prefix] = []; } save_data(save_url, data); return; } } for(var field_name in datum.fields) { handle_field_values(field_name, datum.fields[field_name]); if(field_name == name) { try { $(item).typeahead('setQuery', datum.fields[field_name]); } catch (error) {} //Suppress error } } //FIXME: sends wrong field names save_data(save_url, datum.fields); } } var dropbox_files = []; if (document.getElementById("db-chooser") !== null) { document.getElementById("db-chooser").addEventListener("DbxChooserSuccess", function(e) { $('.pluploader').show(); $('#file-table').show('fast'); $.each(e.files, function(i, file){ id = unique_id(); dbfile = { id: id, name: file.name, size: file.bytes, url: file.link }; $('#filelist').append(tpl_file_entry.render({ id: dbfile.id, filename: file.name, filesize: getBytesWithUnit(file.bytes), removeable: true })); $('#filelist #' + id).show('fast'); $('#uploadfiles').removeClass("disabled"); $('#' + dbfile.id + ' .rmlink').on("click", function(event){ $('#' + dbfile.id).hide('fast', function() { $('#' + dbfile.id).remove(); if($('#filelist').children().length === 0){ $('#uploadfiles').addClass("disabled"); } }); dropbox_files = dropbox_files.filter(function(element){ return element.id != dbfile.id; }); }); dropbox_files.push(dbfile); }); }, false); } /** * Split paste text into multiple fields and elements. */ function paste_newline_splitter(field, data){ return data.split("\n").filter(function (item, idx, array){ return item.trim() !== ""; }).map(function (value){ r = {}; r[field] = value.trim(); return r; }); } /** * */ $.fn.fieldlist = function(opts) { var options = $.extend({}, $.fn.fieldlist.defaults, opts); if (options.prefix === null) { options.prefix = this.attr('id'); } var template = this.find('.' + options.empty_cssclass); var last_index = $("#" + options.prefix + options.sep + options.last_index); var field_regex = new RegExp("(" + options.prefix + options.sep + "(\\d+|" + options.index_suffix + "))"+ options.sep +"(.+)"); // Get template name from options or the empty elements data attribute var tag_template = Hogan.compile($(this).data('tagTemplate') || ''); /** * Get next index */ var get_next_index = function(){ return parseInt(last_index.val(), 10) + 1; }; /** * Set value of last index */ var set_last_index = function(idx){ return last_index.val(idx); }; /** * Update attributes in a single tag */ var update_attr_index = function(tag, idx) { var id_regex = new RegExp("(" + options.prefix + options.sep + "(\\d+|" + options.index_suffix + "))"); var new_id = options.prefix + options.sep + idx; ['for', 'id', 'name'].forEach(function(attr_name){ if($(tag).attr(attr_name)){ $(tag).attr(attr_name, $(tag).attr(attr_name).replace(id_regex, new_id)); } }); }; /** * Update index in attributes for a single element (i.e all tags inside * element) */ var update_element_index = function(element, idx) { update_attr_index(element, idx); $(element).find('*').each(function(){ update_attr_index(this, idx); }); }; /** * Update indexes of all elements */ var update_elements_indexes = function(){ // Update elements indexes of all other elements var all_elements = $('#' + options.prefix + " ." + options.element_css_class); var num_elements = all_elements.length; for (var i=0; i<num_elements; i++) { update_element_index(all_elements[i], i); } set_last_index(num_elements-1); }; /** * Update values of fields for an element */ var update_element_values = function (root, data, field_prefix_index, selector_prefix){ var field_prefix, newdata; if(selector_prefix ===undefined){ selector_prefix = '#'+options.prefix+options.sep+options.index_suffix+options.sep; } if(field_prefix_index === undefined){ field_prefix = options.prefix+options.sep+options.index_suffix+options.sep; } else { field_prefix = options.prefix+options.sep+field_prefix_index+options.sep; } if(root === null) { root = $(document); } //Update field values if data exists if(data !== null){ // Remove prefix from field name newdata = {}; if (typeof data == 'object'){ for(var field in data) { if(field.indexOf(field_prefix) === 0){ newdata[field.slice(field_prefix.length)] = data[field]; } else { newdata[field] = data[field]; } } // Update value for each field. $.each(newdata, function(field, value){ var input = root.find(selector_prefix+field); if(input.length !== 0) { input.val(value); } }); } else { newdata['value'] = data; var input = root.find('#'+options.prefix+options.sep+options.index_suffix); if(input.length !== 0) { // Keep old value input.val(input.val()+data); } } root.find("."+options.tag_title_cssclass).html( tag_template.render(newdata) ); } }; var get_field_name = function(name_or_id) { result = field_regex.exec(name_or_id); if(result !== null){ return result[3]; } return null; }; var get_field_prefix = function(name_or_id) { result = field_regex.exec(name_or_id); if(result !== null){ return result[1]; } return null; }; /** * Handler for remove element events */ var remove_element = function(e){ // // Delete action // e.preventDefault(); // Find and remove element var old_element = $(this).parents("." + options.element_css_class); old_element.hide('fast', function(){ // Give hide animation time to complete old_element.remove(); update_elements_indexes(); // Callback if (options.removed) { options.removed(options, old_element); } }); }; /** * Handler for sort element events */ var sort_element = function (e, ui) { update_elements_indexes(); // Callback if (options.updated) { options.updated(options, ui.item); } }; var update_element = function (data, idx){ // // Update action // // Update elements indexes of all other elements var all_elements = $('#' + options.prefix + " ." + options.element_css_class); var num_elements = all_elements.length; if (idx < num_elements){ element = $(all_elements[idx]); update_element_values(element, data, idx, '#'+options.prefix+options.sep+idx+options.sep); } }; /** * Handler for add new element events */ var append_element = function (data, field_prefix_index){ // // Append action // var new_element = template.clone(); var next_index = get_next_index(); // Remove class new_element.removeClass(options.empty_cssclass); new_element.addClass(options.element_css_class); new_element.addClass("input-group"); // Pre-populate field values update_element_values(new_element, data, field_prefix_index); // Update ids update_element_index(new_element, next_index); // Insert before template element new_element.hide(); new_element.insertBefore($(template)); new_element.show('fast'); // Update last_index set_last_index(next_index); // Add delete button handler new_element.find('.' + options.remove_cssclass).click(remove_element); // Add paste handler for some fields if( options.on_paste !== null && options.on_paste_elements !== null) { new_element.find(options.on_paste_elements).on('paste', on_paste); } // Callback if (options.added) { options.added(options, new_element); } }; /** * On paste event handler, wrapping the user-defined paste handler to * for ease of use. */ var on_paste = function (e){ var element = $(e.target); var root_element = element.parents("." + options.element_css_class); var data = e.originalEvent.clipboardData.getData("text/plain"); var field_name = get_field_name(element.attr("id")); var prefix = "#" + get_field_prefix(element.attr("id")) + options.sep; if(options.on_paste !== null && data !== null) { if(options.on_paste(root_element, element, prefix, field_name, data, append_element)) { e.preventDefault(); } } }; /** * Factory method for creating on paste event handlers. Allow handlers to * only care about splitting string into data elements. */ var create_paste_handler = function (splitter){ var on_paste_handler = function(root_element, element, selector_prefix, field, clipboard_data, append_element){ var elements_values = splitter(field, clipboard_data); if(elements_values.length > 0) { $.each(elements_values, function(idx, clipboard_data){ if(idx === 0) { update_element_values(root_element, clipboard_data, undefined, selector_prefix); } else { append_element(clipboard_data); } }); // Callback if (options.pasted) { options.pasted(options); } return true; } else { return false; } }; return on_paste_handler; }; var create = function(item){ // Hook add/remove buttons on already rendered elements $('#' + options.prefix + " ." + options.element_css_class + " ." + options.remove_cssclass).click(remove_element); $('#' + options.prefix + " ." + options.add_cssclass).click(append_element); // Hook for detecting on paste events if( options.on_paste !== null && options.on_paste_elements !== null) { options.on_paste = create_paste_handler(options.on_paste); $('#' + options.prefix + " " + options.on_paste_elements).on('paste', on_paste); } // Make list sortable if(options.sortable){ var sortable_options = { items: "." + options.element_css_class, update: sort_element, }; if($(item).find("."+options.sort_cssclass).length !== 0){ sortable_options.handle = "." + options.sort_cssclass; } $(item).sortable(sortable_options); } return item; }; create(this); return { append_element: append_element, update_element: update_element, options: options, }; }; /** Field list plugin defaults */ $.fn.fieldlist.defaults = { prefix: null, sep: '-', last_index: "__last_index__", index_suffix: "__index__", - empty_cssclass: "empty-element", + empty_cssclass: empty_cssclass, element_css_class: "field-list-element", remove_cssclass: "remove-element", add_cssclass: "add-element", sort_cssclass: "sort-element", tag_title_cssclass: "tag-title", added: null, removed: null, updated: null, pasted: null, on_paste_elements: "input", on_paste: null, //paste_newline_splitter, sortable: true, js_template: null, }; // Return public methods return { check_status: check_status, clear_error: clear_error, create_deposition: create_deposition, flash_message: _flash_message, getBytesWithUnit: getBytesWithUnit, handle_field_msg: handle_field_msg, handle_field_values: handle_field_values, handle_response: handle_response, init_autocomplete: init_autocomplete, - init_bootstrap_typeahead: init_bootstrap_typeahead, init_buttons: init_buttons, init_ckeditor: init_ckeditor, init_field_lists: init_field_lists, init_inputs: init_inputs, init_plupload: init_plupload, init_save: init_save, init_submit: init_submit, init_typeaheadjs: init_typeaheadjs, json_options: json_options, paste_newline_splitter: paste_newline_splitter, save_data: save_data, save_field: save_field, serialize_files: serialize_files, serialize_form: serialize_form, serialize_object: serialize_object, set_loader: set_loader, set_status: set_status, submit: submit, typeahead_selection: typeahead_selection, unique_id: unique_id, }; }( window.jQuery )); diff --git a/invenio/modules/deposit/templates/deposit/run_base.html b/invenio/modules/deposit/templates/deposit/run_base.html index 4e84fe8e6..a889f2595 100644 --- a/invenio/modules/deposit/templates/deposit/run_base.html +++ b/invenio/modules/deposit/templates/deposit/run_base.html @@ -1,240 +1,198 @@ {# ## This file is part of Invenio. ## Copyright (C) 2013 CERN. ## ## Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## Invenio is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. #} {%- block webdeposit_assets %} {% js 'js/jqueryui/jquery-ui.js', '01-jquery-ui' %} {% js 'js/jqueryui/jquery.ui.core.js', '01-jquery-ui' %} {% js 'js/jqueryui/jquery.ui.widget.js', '01-jquery-ui' %} {% js 'js/jqueryui/jquery.ui.mouse.js', '01-jquery-ui' %} {% js 'js/jqueryui/jquery.ui.sortable.js', '01-jquery-ui' %} {% js 'plupload/plupload.full.min.js', '50-webdeposit' %} {% js url_for('webdeposit.static', filename='js/deposit/form.js'), '50-webdeposit' %} {% js 'js/hogan.js', '40-webdeposit-hogan' %} {% js url_for('webdeposit.static', filename='js/deposit/templates.js'), '50-webdeposit' %} {% js 'ckeditor/ckeditor.js', '50-ckeditor' %} {% js 'js/ckeditor/invenio-ckeditor-config.js', '50-ckeditor' %} + {%- js 'js/typeahead.js', '10-invenio' -%} + {%- css url_for('static', filename='css/typeahead.js-bootstrap.css'), '50-webdeposit' -%} + {%- css url_for('static', filename='css/deposit/form.css'), '51-webdeposit' -%} {% css 'img/jquery-ui/themes/base/jquery.ui.theme.css', '01-jquery-ui' %} {% css 'img/jquery-ui/themes/base/jquery.ui.datepicker.css', '01-jquery-ui' %} {%- endblock webdeposit_assets %} {% extends "page.html" %} {% macro form_action_bar(margin="") -%} {% include "deposit/run_action_bar.html" %} {%- endmacro %} {%- macro form_group_accordion_start(group, idx) -%} {% include "deposit/run_group_start.html" %} {%- endmacro -%} {%- macro form_group_accordion_end(group, idx) -%} {% include "deposit/run_group_end.html" %} {%- endmacro -%} {%- macro field_label(thisfield) -%} {% include "deposit/run_field_label.html" %} {%- endmacro -%} {%- macro field_display(thisfield, field_size=None, field_class="form-control", container_class="form-group") -%} {% include "deposit/run_field.html" %} {%- endmacro -%} {%- macro field_display_subform(thisfield) -%} {% include "deposit/run_field_subform.html" %} {%- endmacro -%} {%- block css %} {{ super() }} -<style> -.ui-autocomplete-loading { - background: white url('{{ url_for('static', filename='img/loading.gif') }}') right top no-repeat; -} - -span.ui-icon.ui-icon-circle-triangle-w { color: transparent; cursor: pointer; } -span.ui-icon.ui-icon-circle-triangle-e { color: transparent; cursor: pointer; } - -/*.typeahead { - max-height: 250px; - overflow-y: auto; - /* prevent horizontal scrollbar */ - /*overflow-x: hidden;*/ -/*}*/ - -.l{ - size: 10px; -} - -.required:after { - color: red; - content:" *"; -} - -.rmlink { - cursor: pointer; -} -.sortlink { - cursor: move; - margin-left: 10px; -} -.empty-element { - display: none; -} -.sortlink:hover { - cursor: move; -} -.remove-element { - padding-left: 10px; -} -.field-list-element { - margin-bottom: 10px; -} -.field-list-element ul.inline { - margin: 0; -} -.tag { - cursor: move; -} -</style> + <style> + .ui-autocomplete-loading { + background: white url('{{ url_for('static', filename='img/loading.gif') }}') right top no-repeat; + } + </style> {%- endblock css %} {% block body %} {% block form_submit_dialog %} <div id="form-submit-dialog" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="{{id}}Label" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-body"> <div align="center" id="{{id}}Label">Submitting <img src="/img/loading.gif" /></div> </div> </div> </div> </div> {% endblock form_submit_dialog %} <div class="row"> <div id="file_container" class="col-md-8 form-feedback-warning"> <div id="flash-message"></div> <form enctype="multipart/form-data" name="submitForm" id="submitForm" role="form" class="form-horizontal" method="post" action="{{ url_for('.run', deposition_type=deposition_type, uuid=uuid) }}"> {% block form_header scoped %}{{ form_action_bar() }}{% endblock form_header%} {% block form_title scoped %} <h1>{{ form._title }}</h1> {% if form._subtitle %} <p class="text-muted"><small>{{ form._subtitle|safe }}</small></p> {% endif %} {% endblock form_title %} {% block form_body scoped %} {% for group, fields in form.get_groups() %} {% set grouploop = loop %} {% block form_group scoped %} {% if grouploop.first %} <div id="webdeposit_form_accordion"> {% endif %} {% block form_group_header scoped %} {% if group %} {{ form_group_accordion_start(group, grouploop.index) }} {% endif %} {% endblock %} {% block form_group_body scoped %} {% if group and group.meta.description %} <p>{{ group.meta.description|urlize }}</p> {% endif %} {% block fieldset scoped %} {% for field in fields %} {% block field_body scoped %} - {{ field_display(field) }} + {{ field_display(field, field_class="") }} {% endblock field_body %} {% endfor %} {% endblock fieldset %} {% endblock form_group_body%} {% block form_group_footer scoped %} {% if group %} {{ form_group_accordion_end(group, grouploop.index) }} {% endif %} {% endblock form_group_footer %} {% if grouploop.last %}</div>{% endif %} {% endblock form_group %} {% endfor %} {% endblock form_body %} {% block form_footer scoped %}{{ form_action_bar() }}{% endblock form_footer %} </form> </div> {% if form._drafting %} <div class="col-md-4"> {% include "deposit/myview.html" %} </div> {% endif %} </div> </div> {% endblock %} {% block javascript %} {{ super() }} {%- block form_script_options %} <script type="text/javascript"> var date_options = {dateFormat: 'yy-mm-dd'} </script> {%- endblock form_script_options %} <script type="text/javascript" src="https://www.dropbox.com/static/api/1/dropbox.js" id="dropboxjs" data-app-key="{{config.CFG_DROPBOX_API_KEY}}"></script> <script type="text/javascript"> $(document).ready(function() { {# Fix issue with typeahead.js drop-down partly cut-off due to overflow #} $('#webdeposit_form_accordion').on('hide', function (e) { $(e.target).css("overflow","hidden"); }) $('#webdeposit_form_accordion').on('shown', function (e) { $(e.target).css("overflow", "visible"); }) $('#webdeposit_form_accordion .panel-collapse.in.collapse').css("overflow", "visible"); }); $(document).ready(function() { var save_url = '{{ url_for(".save", deposition_type=deposition_type, uuid=uuid, draft_id=draft.id) }}'; var save_all_url = '{{ url_for(".save", deposition_type=deposition_type, uuid=uuid, draft_id=draft.id, all='1') }}'; var complete_url = '{{ url_for(".save", deposition_type=deposition_type, uuid=uuid, draft_id=draft.id, submit='1') }}'; var autocomplete_url = '{{ url_for(".autocomplete", deposition_type=deposition_type, uuid=uuid, draft_id=draft.id, field_name="__FIELDNAME__") }}'; DEPOSIT_FORM.init_plupload( '{{config.DEPOSIT_MAX_UPLOAD_SIZE|default('10mb')}}', '.pluploader', save_url, '{{ url_for('.upload_file', deposition_type=deposition_type, uuid=uuid) }}', '{{ url_for('.delete_file', deposition_type=deposition_type, uuid=uuid) }}', '{{ url_for('.get_file', deposition_type=deposition_type, uuid=uuid) }}', {{ form.files|safe }}, '{{ url_for('.upload_url', deposition_type=deposition_type, uuid=uuid) }}' ); DEPOSIT_FORM.init_save(save_all_url, '.form-save', '#submitForm'); DEPOSIT_FORM.init_submit(complete_url, '.form-submit', '#submitForm', '#form-submit-dialog'); DEPOSIT_FORM.init_inputs('#submitForm input, #submitForm textarea, #submitForm select', save_url); DEPOSIT_FORM.init_buttons('#submitForm .form-button', save_url); DEPOSIT_FORM.init_autocomplete('[data-autocomplete="1"]', save_url, autocomplete_url); DEPOSIT_FORM.init_field_lists('#submitForm .dynamic-field-list', save_url, '[data-autocomplete="1"]', autocomplete_url); DEPOSIT_FORM.init_ckeditor( '#submitForm textarea[data-ckeditor="1"]', save_url); // Date picker $(".datepicker").datepicker(date_options); //DEPOSIT_FORM.check_status('{{ url_for('.status', deposition_type=deposition_type, uuid=uuid, draft_id=draft.id) }}'); }); </script> {% endblock javascript %} diff --git a/invenio/modules/deposit/templates/deposit/run_field_subform.html b/invenio/modules/deposit/templates/deposit/run_field_subform.html index c72a01046..386feeb93 100644 --- a/invenio/modules/deposit/templates/deposit/run_field_subform.html +++ b/invenio/modules/deposit/templates/deposit/run_field_subform.html @@ -1,7 +1,7 @@ <div class="form-group {{ "error" if thisfield.errors }}" id="state-group-{{ thisfield.name }}"> {{ field_label(thisfield) }} </div> {% for subfield in thisfield.form %} - {{ field_display( subfield )}} + {{ field_display( subfield, field_class="" )}} {% endfor %} <hr /> \ No newline at end of file diff --git a/invenio/modules/search/templates/search/searchbar_frame.html b/invenio/modules/search/templates/search/searchbar_frame.html index ab16e9235..72235ecd2 100644 --- a/invenio/modules/search/templates/search/searchbar_frame.html +++ b/invenio/modules/search/templates/search/searchbar_frame.html @@ -1,47 +1,52 @@ {# ## This file is part of Invenio. ## Copyright (C) 2012 CERN. ## ## Invenio is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as ## published by the Free Software Foundation; either version 2 of the ## License, or (at your option) any later version. ## ## Invenio is distributed in the hope that it will be useful, but ## WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. #} {% from "_formhelpers.html" import render_filter_form with context %} {% from "search/helpers.html" import collection_tree, portalbox_sidebar, search_also, search_form, search_form_javascript, record_brief_links with context %} {% extends "page.html" %} {# set title = collection.name_ln if collection.id > 1 else None #} {% block header %} {{ super() }} {% js url_for('search.static', filename='js/search/typeahead.js') %} {% js url_for('search.static', filename='js/search/facet.js') %} {% js url_for('static', filename='js/bootstrap-select.js') %} {% js "js/jquery.hotkeys.js" %} {% js url_for('search.static', filename='js/search/hotkeys.js') %} {% endblock %} +{% block css %} + {%- css url_for('static', filename='css/search/typeahead.js-bootstrap.css'), '50-webdeposit' -%} +{% endblock %} + {% block body %} {%- block search_form -%} {{ search_form(collection, easy_search_form) }} {%- endblock %} {% block inner_content %} {% endblock %} {% endblock %} {% block javascript %} + {%- js 'js/typeahead.js', '10-invenio' -%} {{ super() }} {{ search_form_javascript(collection) }} {% endblock %}