├── robots.txt ├── docs ├── manual.odt ├── manual.pdf └── img │ ├── SearchBar.jpg │ ├── SketcherLeftToolbar.jpg │ ├── SketcherTopToolbar.jpg │ └── SketcherRightToolbar.jpg ├── pages ├── 400.md ├── 404.md ├── 403.md ├── 401.md ├── 500.md ├── iesupport.md ├── htmlcanvas.md └── tracking.md ├── .editorconfig ├── .gitignore ├── bower.json ├── minerals.sh ├── package.json ├── src ├── svg │ ├── action │ │ ├── rect.svg │ │ ├── move.svg │ │ ├── chain.svg │ │ ├── undo.svg │ │ ├── redo.svg │ │ ├── clean.svg │ │ ├── erase.svg │ │ ├── lasso.svg │ │ ├── center.svg │ │ ├── hstrip.svg │ │ ├── rotate.svg │ │ ├── color.svg │ │ ├── skeletal-off.svg │ │ └── clear.svg │ ├── bond │ │ ├── single.svg │ │ ├── double.svg │ │ ├── wedge.svg │ │ ├── triple.svg │ │ └── hash.svg │ ├── frag │ │ ├── cyclobutane.svg │ │ ├── cyclopropane.svg │ │ ├── cyclohexane.svg │ │ ├── cyclopentane.svg │ │ ├── cycloheptane.svg │ │ └── benzene.svg │ └── misc │ │ └── spinner.svg ├── less │ ├── model.less │ ├── menu-touch.less │ ├── smooth.less │ ├── embed.less │ ├── menu-desktop.less │ ├── vars.less │ ├── help.less │ ├── periodictable.less │ ├── welcome.less │ ├── messages.less │ ├── dialogs.less │ ├── autocomplete.less │ ├── page.less │ ├── share.less │ ├── active.less │ ├── global.less │ ├── layout.less │ ├── chemicaldata.less │ ├── hover.less │ ├── menu-theme.less │ ├── search.less │ ├── menu.less │ └── form.less ├── js │ ├── chem │ │ ├── prototype.js │ │ ├── util │ │ │ ├── pool.js │ │ │ ├── map.js │ │ │ └── set.js │ │ └── chem │ │ │ └── dfs.js │ ├── lib │ │ ├── Detector.js │ │ └── Polyfill.js │ ├── History.js │ ├── Preferences.js │ ├── molpad │ │ ├── Data.js │ │ ├── MPLine.js │ │ ├── MPSelection.js │ │ ├── MolPad.js │ │ ├── MPFragments.js │ │ └── Utility.js │ ├── MolView.Embed.js │ ├── Link.js │ ├── Share.js │ └── Loader.Embed.js └── datasets │ └── JmolColors.js ├── licenses └── mit.txt ├── php ├── gplus.php ├── image.php ├── utility.php ├── cif.php ├── load.php └── nist.php ├── .htaccess ├── README.md ├── LEGAL.md ├── page.php ├── embed.php └── LICENSE.md /robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | -------------------------------------------------------------------------------- /docs/manual.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/molview/master/docs/manual.odt -------------------------------------------------------------------------------- /docs/manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/molview/master/docs/manual.pdf -------------------------------------------------------------------------------- /docs/img/SearchBar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/molview/master/docs/img/SearchBar.jpg -------------------------------------------------------------------------------- /docs/img/SketcherLeftToolbar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/molview/master/docs/img/SketcherLeftToolbar.jpg -------------------------------------------------------------------------------- /docs/img/SketcherTopToolbar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/molview/master/docs/img/SketcherTopToolbar.jpg -------------------------------------------------------------------------------- /pages/400.md: -------------------------------------------------------------------------------- 1 | Error 2 | ===== 3 | 400 - Bad request 4 | ----------------- 5 | There was an error in your request. 6 | -------------------------------------------------------------------------------- /docs/img/SketcherRightToolbar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thinkcmf/molview/master/docs/img/SketcherRightToolbar.jpg -------------------------------------------------------------------------------- /pages/404.md: -------------------------------------------------------------------------------- 1 | Error 2 | ===== 3 | 404 - Not found 4 | --------------- 5 | The requested URL was not found on this server. 6 | -------------------------------------------------------------------------------- /pages/403.md: -------------------------------------------------------------------------------- 1 | Error 2 | ===== 3 | 403 - Forbidden 4 | --------------- 5 | You don't have permission to access the requested data. 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | charset = utf-8 7 | indent_style = tab 8 | indent_size = 2 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | api 2 | /node_modules 3 | /bower_components 4 | /img 5 | /build 6 | /jmol 7 | /project 8 | /*.png 9 | favicon.ico 10 | .directory 11 | -------------------------------------------------------------------------------- /pages/401.md: -------------------------------------------------------------------------------- 1 | Error 2 | ===== 3 | 401 - Authorization required 4 | ---------------------------- 5 | This server could not verify if you are authorized to access the requested data. 6 | -------------------------------------------------------------------------------- /pages/500.md: -------------------------------------------------------------------------------- 1 | Error 2 | ===== 3 | 500 - Internal server error 4 | --------------------------- 5 | The server encountered an internal error and was unable to complete your request. 6 | -------------------------------------------------------------------------------- /pages/iesupport.md: -------------------------------------------------------------------------------- 1 | Your browser is not supported! 2 | ============================== 3 | MolView is not supported on Internet Explorer 9 and below. 4 | Download [Google Chrome](//google.com/chrome) or upgrade Internet Explorer. 5 | -------------------------------------------------------------------------------- /pages/htmlcanvas.md: -------------------------------------------------------------------------------- 1 | MolView requires HTML5 Canvas support! 2 | ============================================= 3 | The HTML5 Canvas is used to draw 2D and 3D visualizations. 4 | Install the latest version of [Google Chrome](//google.com/chrome) to resolve this issue. 5 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "molview", 3 | "version": "2.4.6", 4 | "authors": [ 5 | "Herman Bergwerf " 6 | ], 7 | "description": "MolView is an intuitive, Open-Source web-application to make chemistry and biology more awesome!", 8 | "license": "AGPL", 9 | "homepage": "http://molview.org", 10 | "private": true, 11 | "ignore": [ 12 | "**/.*", 13 | "node_modules", 14 | "bower_components", 15 | "test", 16 | "tests" 17 | ], 18 | "dependencies": { 19 | "jquery": "~2.1.1", 20 | "jquery.hotkeys": "jeresig/jquery.hotkeys#~0.2.0", 21 | "file-saver": "*", 22 | "blob": "*" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /pages/tracking.md: -------------------------------------------------------------------------------- 1 | Event tracking 2 | ============== 3 | MolView tracks a number of events like changing the model representation using 4 | Google Analytics in order to analyze the usage and popularity of all features 5 | included in MolView. We can use this information to find out which features are 6 | used more and might deserve more development. Usage statics are stored by Google 7 | and are believed to be anonymous. Google will not share this data with 8 | third parties unless any of the exceptions in part 6 of the Google Analytics 9 | Terms of Service (http://www.google.com/analytics/terms/us.html) is in effect. 10 | 11 | You can enable and disable event tracking by reloading MolView and un-checking 12 | "Allow MolView to collect interaction data" 13 | -------------------------------------------------------------------------------- /minerals.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Selects all minerals from the COD database and writes them to src/datasets/MineralNames.json 4 | # Formatted using SED as: 5 | # var MineralNames = { 6 | # "records": [ 7 | # { "name": "Agaite", "codid": "9016323" }, 8 | # { "name": "Ajoite", "codid": "9009649" } 9 | # ] 10 | # } 11 | 12 | mysql -N -u cod_reader -h www.crystallography.net -e 'SELECT mineral,file FROM data WHERE (mineral RLIKE "^[A-Z]" AND mineral NOT RLIKE "\t" AND mineral NOT LIKE "%?%" AND mineral <> "" AND mineral IS NOT NULL AND flags LIKE "%has coordinates%") GROUP BY mineral' cod | sed -e 's/\t/", "codid": "/g' -e 's/^/\t\t{ "name": "/g' -e 's/$/" },/g' -e '1 s/^/var MineralNames = {\n\t"records": [\n/' -e '$s/,$/\n\t]\n}/' > src/datasets/MineralNames.js 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "molview", 3 | "version": "2.4.6", 4 | "authors": [ 5 | "Herman Bergwerf " 6 | ], 7 | "description": "MolView is an intuitive, Open-Source web-application to make chemistry and biology more awesome!", 8 | "license": "AGPL", 9 | "homepage": "http://molview.org", 10 | "private": true, 11 | "devDependencies": { 12 | "grunt": "^1.0.3", 13 | "grunt-contrib-clean": "~0.6.0", 14 | "grunt-contrib-copy": "~0.5.0", 15 | "grunt-contrib-jshint": "^2.0.0", 16 | "grunt-contrib-less": "^2.0.0", 17 | "grunt-contrib-nodeunit": "~0.3.3", 18 | "grunt-contrib-uglify": "~0.4.0", 19 | "grunt-contrib-watch": "^1.1.0", 20 | "grunt-svgmin": "^5.0.0", 21 | "grunt-text-replace": "~0.3.12" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/svg/action/rect.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | image/svg+xml 4 | -------------------------------------------------------------------------------- /src/svg/bond/single.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | Created with Raphaël 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/svg/frag/cyclobutane.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | Created with Raphaël 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/svg/frag/cyclopropane.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | Created with Raphaël 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/svg/bond/double.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | Created with Raphaël 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/svg/bond/wedge.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | Created with Raphaël 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/svg/frag/cyclohexane.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | Created with Raphaël 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/svg/bond/triple.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | Created with Raphaël 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/less/model.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | .render-engine 20 | { 21 | z-index: 0; 22 | display: block; 23 | position: absolute; 24 | top: 0; 25 | left: 0; 26 | right: 0; 27 | bottom: 0; 28 | } 29 | -------------------------------------------------------------------------------- /src/svg/action/move.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | image/svg+xml 4 | -------------------------------------------------------------------------------- /src/svg/frag/cyclopentane.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | Created with Raphaël 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/svg/frag/cycloheptane.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | Created with Raphaël 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/less/menu-touch.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | .dropdown-toggle 20 | { 21 | font-size: 14pt; 22 | } 23 | 24 | .menu-header 25 | { 26 | font-size: 10pt; 27 | } 28 | 29 | .menu-item > a 30 | { 31 | padding: 7px 40px 7px 5px; 32 | font-size: 14pt; 33 | } 34 | -------------------------------------------------------------------------------- /licenses/mit.txt: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any person obtaining a copy 2 | of this software and associated documentation files (the "Software"), to deal 3 | in the Software without restriction, including without limitation the rights 4 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5 | copies of the Software, and to permit persons to whom the Software is 6 | furnished to do so, subject to the following conditions: 7 | 8 | The above copyright notice and this permission notice shall be included in 9 | all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 17 | THE SOFTWARE. 18 | -------------------------------------------------------------------------------- /src/js/chem/prototype.js: -------------------------------------------------------------------------------- 1 | Array.prototype.each = function(iterator, context) 2 | { 3 | for(var i = 0, length = this.length >>> 0; i < length; i++) 4 | { 5 | if(i in this) 6 | { 7 | if(iterator.call(context, this[i], i, this) === false) 8 | return; 9 | } 10 | } 11 | } 12 | 13 | Array.prototype.clone = function() 14 | { 15 | return Array.prototype.slice.call(this, 0); 16 | } 17 | 18 | Array.prototype.find = function() 19 | { 20 | var result; 21 | this.each(function(value, index) 22 | { 23 | if(iterator.call(context, value, index, this)) 24 | { 25 | result = value; 26 | return false; 27 | } 28 | return true; 29 | }, this); 30 | return result; 31 | } 32 | 33 | Array.prototype.findAll = function() 34 | { 35 | var results = []; 36 | this.each(function(value, index) 37 | { 38 | if(iterator.call(context, value, index, this)) 39 | results.push(value); 40 | }, this); 41 | return results; 42 | } 43 | 44 | Number.prototype.toPaddedString = function(n) 45 | { 46 | var str = this + ''; 47 | return str.length >= n ? str : new Array(n - str.length + 1).join('0') + str; 48 | } 49 | -------------------------------------------------------------------------------- /src/svg/action/chain.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | Created with Raphaël 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/svg/action/undo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | image/svg+xml 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/less/smooth.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | .social .share span:after 20 | { 21 | transition: opacity .2s ease-in; 22 | } 23 | 24 | /* search results transitions */ 25 | .result 26 | { 27 | transition: border .1s ease-in; 28 | } 29 | 30 | .search-results .more 31 | { 32 | transition: background .1s ease-in, color .1s ease-in; 33 | } 34 | -------------------------------------------------------------------------------- /src/svg/action/redo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | image/svg+xml 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/js/lib/Detector.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * @author mr.doob / http://mrdoob.com/ 4 | */ 5 | 6 | var Detector = { 7 | canvas: !! window.CanvasRenderingContext2D, 8 | webgl: ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( 'canvas' ).getContext( 'experimental-webgl' ); } catch( e ) { return false; } } )(), 9 | workers: !! window.Worker, 10 | fileapi: window.File && window.FileReader && window.FileList && window.Blob, 11 | 12 | getWebGLErrorMessage: function() 13 | { 14 | var msg = "Your browser supports WebGL"; 15 | if(!this.webgl) 16 | { 17 | msg = window.WebGLRenderingContext ? 18 | 'Your graphics card does not seem to support WebGL. Find out how to get it here.' 19 | : 20 | 'Your browser does not seem to support WebGL. Find out how to get it here.'; 21 | 22 | } 23 | return msg; 24 | }, 25 | }; 26 | -------------------------------------------------------------------------------- /src/less/embed.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | html 20 | { 21 | overflow: hidden; 22 | } 23 | 24 | body 25 | { 26 | position: absolute; 27 | margin: 0; 28 | padding: 0; 29 | width: 100%; 30 | height: 100%; 31 | 32 | font-family: 'Open Sans', sans-serif; 33 | background: #000; 34 | overflow: hidden; 35 | } 36 | 37 | .progress-cursor 38 | { 39 | cursor: progress; 40 | } 41 | -------------------------------------------------------------------------------- /src/less/menu-desktop.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "vars"; 20 | 21 | .dropdown-toggle 22 | { 23 | font-size: 12pt; 24 | } 25 | 26 | .dropdown-menu 27 | { 28 | box-shadow: 0 10px 30px @contrast; 29 | box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); 30 | } 31 | 32 | .dropdown.open > .dropdown-toggle 33 | { 34 | box-shadow: 0 -10px 10px @dark-shadow; 35 | } 36 | 37 | .menu-header 38 | { 39 | font-size: 8pt; 40 | } 41 | 42 | .menu-item > a 43 | { 44 | padding: 5px 40px 5px 5px; 45 | font-size: 12pt; 46 | } 47 | -------------------------------------------------------------------------------- /php/gplus.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | include_once("utility.php"); 21 | 22 | error_reporting(0); 23 | parse_str($_SERVER["QUERY_STRING"]); 24 | 25 | header('content-type: application/json'); 26 | 27 | libxml_use_internal_errors(true); 28 | 29 | $html = http_get("https://plusone.google.com/_/+1/fastbutton?url=".urlencode($url)); 30 | $doc = new DOMDocument(); 31 | $doc -> loadHTML($html); 32 | $counter = $doc -> getElementById('aggregateCount'); 33 | echo '{ "count": '.json_encode($counter -> nodeValue)."}"; 34 | 35 | libxml_clear_errors(); 36 | -------------------------------------------------------------------------------- /src/svg/action/clean.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | image/svg+xml -------------------------------------------------------------------------------- /src/svg/action/erase.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | image/svg+xml -------------------------------------------------------------------------------- /src/svg/action/lasso.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | image/svg+xml -------------------------------------------------------------------------------- /php/image.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | /* 21 | PHP script for mirroring metadata images 22 | 23 | @param dbid Database ID 24 | @param i Database index 25 | */ 26 | 27 | include_once("utility.php"); 28 | 29 | error_reporting(0); 30 | parse_str($_SERVER["QUERY_STRING"]); 31 | 32 | if($dbid == "cid") 33 | { 34 | header("Content-Type: image/png"); 35 | echo_curl("https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/cid/".$i."/png?record_type=2d"); 36 | exit; 37 | } 38 | else if($dbid == "pdb") 39 | { 40 | header("Content-Type: image/jpeg"); 41 | echo_curl("http://www.rcsb.org/pdb/images/".strtoupper($i)."_bio_r_500.jpg"); 42 | exit; 43 | } 44 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | Options +FollowSymlinks 2 | RewriteEngine on 3 | 4 | ErrorDocument 400 /page.php?id=400 5 | ErrorDocument 401 /page.php?id=401 6 | ErrorDocument 403 /page.php?id=403 7 | ErrorDocument 404 /page.php?id=404 8 | ErrorDocument 500 /page.php?id=500 9 | 10 | # HTTPS redirection 11 | # RewriteCond %{HTTP:CF-Visitor} '"scheme":"http"' 12 | # RewriteRule ^(.*)$ http://molview.org/$1 [R,L] 13 | 14 | # WWW redirection 15 | RewriteCond %{HTTP_HOST} ^www.molview.org$ [NC] 16 | RewriteRule ^(.*)$ http://molview.org/$1 [L,R=301] 17 | 18 | # PHP APIs 19 | RewriteRule ^api\/cod\/cif\/([^.]*) php/cif.php?codid=$1 [L] 20 | RewriteRule ^api\/cod\/([a-z]*)\/(.*) php/cod.php?action=$1&q=$2 [L] 21 | 22 | RewriteRule ^api\/nist\/lookup\/(.*) php/nist.php?type=lookup&cas=$1 [L] 23 | RewriteRule ^api\/nist\/ir\/([^/]*)\/(.*) php/nist.php?type=ir&cas=$1&i=$2 [L] 24 | RewriteRule ^api\/nist\/mass\/(.*) php/nist.php?type=mass&cas=$1 [L] 25 | RewriteRule ^api\/nist\/uvvis\/(.*) php/nist.php?type=uvvis&cas=$1 [L] 26 | 27 | RewriteRule ^api\/image\/([a-z]*)\/([^.]*) php/image.php?dbid=$1&i=$2 [L] 28 | 29 | RewriteRule ^api\/gplus$ php/gplus.php$1 [L] 30 | 31 | # Markdown pages 32 | RewriteRule ^readme$ page.php?id=readme [L] 33 | RewriteRule ^changelog$ page.php?id=changelog [L] 34 | RewriteRule ^license$ page.php?id=license [L] 35 | RewriteRule ^legal$ page.php?id=legal [L] 36 | RewriteRule ^internetExplorer$ page.php?id=iesupport [L] 37 | RewriteRule ^htmlCanvas$ page.php?id=htmlcanvas [L] 38 | RewriteRule ^tracking$ page.php?id=tracking [L] 39 | -------------------------------------------------------------------------------- /src/svg/bond/hash.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 15 | 17 | 18 | 20 | image/svg+xml 21 | 23 | 24 | 25 | 26 | 27 | 29 | 31 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/svg/action/center.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | image/svg+xml 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/less/vars.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | //dimensions 20 | @menubar-height: 40px; 21 | @toolbar-size: 40px; 22 | @toolbar-iconsize: 20px; 23 | @toolbar-fontsize: 16pt; 24 | @message-bar-height: 45px; 25 | @message-bar-vpad: 20px; 26 | 27 | //colors 28 | @light: #fff; 29 | @light2: #eee; 30 | @light3: #ddd; 31 | @contrast: #ccc; 32 | @contrast2: #bbb; 33 | @contrast3: #aaa; 34 | 35 | @foreground: #111; 36 | @foreground-less: #333; 37 | @foreground-aside: #666; 38 | @foreground-light: #888; 39 | @foreground-lighter: #aaa; 40 | @foreground-disabled: #ccc; 41 | 42 | @light-shadow: #ccc; 43 | @dark-shadow: #888; 44 | 45 | @highlight: #f50; 46 | @highlight-light: #fa8; 47 | @active: #f00; 48 | @linkcolor: #06c; 49 | 50 | @error: #f00; 51 | @error-light: #fcb3bc; 52 | 53 | @pubchem-pngbg: #f5f5f5; 54 | @soft-light: #f5f5f5; 55 | 56 | @menu-bar-bg: #fff; 57 | @search-bar-bg: #fff; 58 | -------------------------------------------------------------------------------- /src/js/lib/Polyfill.js: -------------------------------------------------------------------------------- 1 | //https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind#Polyfill 2 | if (!Function.prototype.bind) { 3 | Function.prototype.bind = function(oThis) { 4 | if (typeof this !== 'function') { 5 | // closest thing possible to the ECMAScript 5 6 | // internal IsCallable function 7 | throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); 8 | } 9 | 10 | var aArgs = Array.prototype.slice.call(arguments, 1), 11 | fToBind = this, 12 | fNOP = function() {}, 13 | fBound = function() { 14 | return fToBind.apply(this instanceof fNOP && oThis 15 | ? this 16 | : oThis, 17 | aArgs.concat(Array.prototype.slice.call(arguments))); 18 | }; 19 | 20 | fNOP.prototype = this.prototype; 21 | fBound.prototype = new fNOP(); 22 | 23 | return fBound; 24 | }; 25 | } 26 | 27 | // Console-polyfill. MIT license. 28 | // https://github.com/paulmillr/console-polyfill 29 | // Make it safe to do console.log() always. 30 | (function(con) { 31 | 'use strict'; 32 | var prop, method; 33 | var empty = {}; 34 | var dummy = function() {}; 35 | var properties = 'memory'.split(','); 36 | var methods = ('assert,clear,count,debug,dir,dirxml,error,exception,group,' + 37 | 'groupCollapsed,groupEnd,info,log,markTimeline,profile,profiles,profileEnd,' + 38 | 'show,table,time,timeEnd,timeline,timelineEnd,timeStamp,trace,warn').split(','); 39 | while (prop = properties.pop()) con[prop] = con[prop] || empty; 40 | while (method = methods.pop()) con[method] = con[method] || dummy; 41 | })(this.console = this.console || {}); // Using `this` for web workers. 42 | -------------------------------------------------------------------------------- /src/less/help.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "form"; 20 | @import (reference) "global"; 21 | 22 | .expandable 23 | { 24 | margin: 10px 0; 25 | } 26 | 27 | .expandable-title 28 | { 29 | cursor: pointer; 30 | position: relative; 31 | padding: 7px 15px; 32 | padding-left: 45px; 33 | 34 | font-size: 12pt; 35 | font-weight: bold; 36 | border: 1px solid @contrast; 37 | 38 | .no-select; 39 | } 40 | 41 | .expandable-title:before 42 | { 43 | display: block; 44 | position: absolute; 45 | top: 0; 46 | left: 0; 47 | bottom: 0; 48 | padding: 0 12px; 49 | 50 | line-height: 38px; 51 | font-size: 14pt; 52 | font-family: FontAwesome; 53 | border-right: 1px solid @contrast; 54 | 55 | content: '\f107'; 56 | } 57 | 58 | .expandable.open > .expandable-title:before 59 | { 60 | content: '\f106'; 61 | } 62 | 63 | .expandable-content 64 | { 65 | display: none; 66 | padding: 10px 10px; 67 | } 68 | 69 | .expandable.open > .expandable-content 70 | { 71 | display: block; 72 | } 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | MolView 2 | ======= 3 | This repository holds the code of MolView.org. 4 | It is not actively maintained due to lacking financial support. 5 | 6 | License 7 | --- 8 | ``` 9 | MolView (http://molview.org) 10 | Copyright (c) 2014, 2015 Herman Bergwerf 11 | 12 | MolView is free software: you can redistribute it and/or modify 13 | it under the terms of the GNU Affero General Public License as published by 14 | the Free Software Foundation, either version 3 of the License, or 15 | (at your option) any later version. 16 | 17 | MolView is distributed in the hope that it will be useful, 18 | but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | GNU Affero General Public License for more details. 21 | 22 | You should have received a copy of the GNU Affero General Public License 23 | along with MolView. If not, see . 24 | ``` 25 | See LICENSE.md for more details about third party code. 26 | 27 | Build 28 | --- 29 | Instructions: 30 | 31 | 1. Copy all files to a server with support for: PHP5, php5-curl, .htaccess and mod_rewrite 32 | 2. Configure $directory in `php/utility.php` to point to the MolView root directory 33 | 3. Configure ErrorDocument in `.htaccess` to point to `page.php` 34 | 4. Make sure the Inkscape and the ImageMagick CLI are installed 35 | 5. Install npm and install local npm modules 36 | 6. Run the build script (use `./build.sh fetch jmol` for a clean build) 37 | - **Only run bower and grunt, and render images:** `./build.sh` 38 | - **Also fetch external PHP sources:** `./build.sh fetch` 39 | - **Also fetch Jmol from sourceforge:** `./build.sh fetch jmol` 40 | - **Also fetch Jmol from stolaf.edu:** `./build.sh fetch jmol nightly` 41 | - **Only render images:** `./build.sh render` 42 | -------------------------------------------------------------------------------- /src/less/periodictable.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "global"; 20 | 21 | #periodictable 22 | { 23 | position: relative; 24 | margin-bottom: 20px; 25 | 26 | .no-select; 27 | } 28 | 29 | #periodictable br 30 | { 31 | clear: both; 32 | } 33 | 34 | .pt-space, .pt-element 35 | { 36 | float: left; 37 | } 38 | 39 | .pt-element 40 | { 41 | cursor: pointer; 42 | text-align: center; 43 | overflow: hidden; 44 | } 45 | 46 | .pt-space, .pt-element 47 | { 48 | width: 30px; 49 | height: 30px; 50 | } 51 | 52 | .pt-element > h3 53 | { 54 | display: none; 55 | margin: 0; 56 | margin-top: 5px; 57 | font-size: 6pt; 58 | } 59 | 60 | .pt-element > h4 61 | { 62 | display: block; 63 | margin: 0; 64 | font-size: 9pt; 65 | line-height: 30px; 66 | } 67 | 68 | @media all and (min-width: 1000px) 69 | { 70 | .pt-space, .pt-element 71 | { 72 | width: 50px; 73 | height: 50px; 74 | } 75 | 76 | .pt-element > h3 77 | { 78 | display: block; 79 | margin: 0; 80 | margin-top: 5px; 81 | font-size: 6pt; 82 | } 83 | 84 | .pt-element > h4 85 | { 86 | display: block; 87 | margin: 0; 88 | font-size: 14pt; 89 | line-height: 20pt; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /php/utility.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | $directory = "/"; 21 | $root = "http://".$_SERVER["HTTP_HOST"].$directory; 22 | 23 | function is_below_IE10() 24 | { 25 | return preg_match('/(?i)msie [0-9]/', $_SERVER['HTTP_USER_AGENT']); 26 | } 27 | 28 | function humanize($str) 29 | { 30 | return preg_replace_callback('/(\b[A-Z]+\b)/', function($words) 31 | { 32 | return strtolower($words[0]); 33 | }, $str); 34 | } 35 | 36 | function is_available($url) 37 | { 38 | $ch = curl_init($url); 39 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); 40 | $out = curl_exec($ch); 41 | $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); 42 | curl_close($ch); 43 | 44 | //if the document has loaded successfully without any redirection or error 45 | if($http_code >= 200 && $http_code < 300) return true; 46 | else return false; 47 | } 48 | 49 | function http_get($url) 50 | { 51 | return file_get_contents($url); 52 | } 53 | 54 | function echo_curl($url) 55 | { 56 | $ch = curl_init($url); 57 | curl_setopt($ch, CURLOPT_HEADER, 0); 58 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 59 | curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); 60 | echo curl_exec($ch); 61 | curl_close($ch); 62 | } 63 | -------------------------------------------------------------------------------- /src/less/welcome.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "vars"; 20 | 21 | #start-dialog 22 | { 23 | padding: 20px 10px; 24 | max-width: 800px; 25 | text-align: center; 26 | } 27 | 28 | @media all and (min-width: 700px) 29 | { 30 | #start-dialog 31 | { 32 | padding: 100px; 33 | } 34 | } 35 | 36 | #start-dialog > h1 37 | { 38 | margin: 0; 39 | font-size: 40pt; 40 | font-weight: lighter; 41 | color: @highlight; 42 | } 43 | 44 | #welcome-logo, #welcome-mark, #agpl-logo-wrapper 45 | { 46 | display: inline-block; 47 | vertical-align: middle; 48 | margin: 10px; 49 | } 50 | 51 | #welcome-logo 52 | { 53 | width: 120px; 54 | margin-right: 10px; 55 | } 56 | 57 | #welcome-mark 58 | { 59 | width: 300px; 60 | } 61 | 62 | #agpl-logo 63 | { 64 | display: block; 65 | height: auto; 66 | } 67 | 68 | #allow-tracking-wrapper 69 | { 70 | margin: 30px; 71 | color: @foreground-lighter; 72 | line-height: 30px; 73 | } 74 | 75 | #welcome-button-bar 76 | { 77 | margin: 10px; 78 | } 79 | 80 | #welcome-loading-msg 81 | { 82 | margin: 30px 0; 83 | font-weight: lighter; 84 | font-size: 20pt; 85 | color: #333; 86 | } 87 | -------------------------------------------------------------------------------- /src/svg/misc/spinner.svg: -------------------------------------------------------------------------------- 1 | 2 | 18 | 20 | 21 | 23 | image/svg+xml 24 | 26 | 27 | 28 | 29 | 31 | 51 | 54 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/less/messages.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "vars"; 20 | 21 | #messages 22 | { 23 | position: absolute; 24 | left: 0; 25 | bottom: 0; 26 | padding: 10px; 27 | } 28 | 29 | .message 30 | { 31 | margin-top: 10px; 32 | min-height: @message-bar-height; 33 | float: left; 34 | clear: both; 35 | 36 | color: @light; 37 | background: @foreground-less; 38 | overflow: hidden; 39 | } 40 | 41 | .alert-message 42 | { 43 | background: @error; 44 | } 45 | 46 | .message-text 47 | { 48 | display: inline-block; 49 | padding: 10px @message-bar-vpad; 50 | line-height: @message-bar-height - 20px; 51 | } 52 | 53 | .error-message 54 | { 55 | padding-left: 5px; 56 | font-style: italic; 57 | font-weight: bold; 58 | } 59 | 60 | .alert-message > .message-text > a 61 | { 62 | font-weight: bold; 63 | color: @light; 64 | } 65 | 66 | .message-close-btn 67 | { 68 | cursor: pointer; 69 | margin: 0; 70 | padding: 0 @message-bar-vpad; 71 | height: @message-bar-height; 72 | float: right; 73 | 74 | color: @light; 75 | font-family: 'Open Sans', sans-serif; 76 | font-size: 12pt; 77 | background: rgba(0, 0, 0, 0.3); 78 | border: 0; 79 | } 80 | 81 | .message-close-btn:focus 82 | { 83 | outline: none; 84 | } 85 | -------------------------------------------------------------------------------- /src/less/dialogs.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "vars"; 20 | 21 | .dialog-overlay 22 | { 23 | position: absolute; 24 | top: 0; 25 | left: 0; 26 | right: 0; 27 | bottom: 0; 28 | 29 | background: rgba(0, 0, 0, 0.3); 30 | 31 | overflow: auto; 32 | } 33 | 34 | #dialog-click-area 35 | { 36 | min-width: 100%; 37 | min-height: 100%; 38 | } 39 | 40 | #dialog-wrapper 41 | { 42 | padding: @menubar-height + 1 10px; 43 | } 44 | 45 | .dialog 46 | { 47 | position: relative; 48 | margin: 0 auto; 49 | padding: 20px; 50 | left: 0px; 51 | right: 0px; 52 | 53 | background: @light; 54 | box-shadow: 0 10px 40px rgba(0, 0, 0, 0.5); 55 | overflow: hidden; 56 | border-radius: 8px; 57 | } 58 | 59 | .dialog h2 60 | { 61 | margin: 0; 62 | margin-bottom: 20px; 63 | 64 | text-align: center; 65 | font-weight: normal; 66 | color: @foreground-less; 67 | } 68 | 69 | .dialog > .footer 70 | { 71 | margin-top: 10px; 72 | text-align: right; 73 | } 74 | 75 | @media all and (min-width: 1060px) 76 | { 77 | #help-dialog, #about-dialog, #share-dialog, #embed-dialog 78 | { 79 | max-width: 960px; 80 | } 81 | } 82 | 83 | /* 84 | Elements dialog 85 | */ 86 | 87 | #periodictable-dialog 88 | { 89 | width: 540px; 90 | } 91 | 92 | @media all and (min-width: 1000px) 93 | { 94 | #periodictable-dialog 95 | { 96 | width: 900px; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/svg/frag/benzene.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 16 | 18 | 19 | 21 | image/svg+xml 22 | 24 | 25 | 26 | 27 | 28 | 31 | 35 | 38 | 42 | 46 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/less/autocomplete.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "vars"; 20 | 21 | #autocomplete-dropdown-wrapper 22 | { 23 | position: absolute; 24 | top: @menubar-height + 1; 25 | left: 0; 26 | right: 0; 27 | bottom: 0; 28 | } 29 | 30 | #autocomplete-dropdown 31 | { 32 | z-index: 1; 33 | position: absolute; 34 | top: 0; 35 | left: 0; 36 | width: 100%; 37 | max-width: 600px; 38 | max-height: 100%; 39 | 40 | overflow: auto; 41 | overflow-x: hidden; 42 | direction: rtl; 43 | } 44 | 45 | #autocomplete-dropdown > ul 46 | { 47 | margin: 0; 48 | padding: 0; 49 | direction: ltr; 50 | } 51 | 52 | .autocomplete-item 53 | { 54 | cursor: pointer; 55 | list-style: none; 56 | margin: 0; 57 | padding: 5px 10px; 58 | 59 | color: #111; 60 | } 61 | 62 | .autocomplete-pubchem { color: #3c763d; background: #dff0d8; border-right: 2px solid #0a0; } 63 | .autocomplete-macromolecule { color: #a94442; background: #f2dede; border-right: 2px solid #f10; } 64 | .autocomplete-mineral { color: #31708f; background: #d9edf7; border-right: 2px solid #07f; } 65 | 66 | .autocomplete-item-hover 67 | { 68 | border-width: 3px; 69 | } 70 | 71 | .autocomplete-item-active 72 | { 73 | color: @foreground; 74 | background: @highlight-light; 75 | border-color: @highlight !important; 76 | border-width: 3px; 77 | } 78 | 79 | .autocomplete-type 80 | { 81 | float: right; 82 | margin: 0 10px; 83 | font-style: italic; 84 | } 85 | -------------------------------------------------------------------------------- /src/js/History.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | /** 20 | * Wrapper for the History API 21 | * This object is mainly used in Loader.js 22 | * @type {Object} 23 | */ 24 | var History = { 25 | /** 26 | * Initialize History API 27 | */ 28 | init: function() 29 | { 30 | window.addEventListener('popstate', function(event) 31 | { 32 | var q = getQuery(); 33 | if(JSON.stringify(q) !== JSON.stringify(MolView.query)) 34 | { 35 | document.title = "MolView"; 36 | MolView.query = q; 37 | MolView.executeQuery(); 38 | } 39 | }); 40 | }, 41 | 42 | /** 43 | * Push new URL into web History 44 | * This URL only contains one parameter 45 | * @param {String} key Parameter key 46 | * @param {String} value Parameter value 47 | * @param {Boolean} forceReplace Force usage of replaceState 48 | */ 49 | push: function(id, value, forceReplace) 50 | { 51 | value = "" + value; 52 | MolView.query = {}; 53 | MolView.query[id] = value; 54 | var query = id + "=" + specialEncodeURIComponent(value.replace(/^ /, "")); 55 | 56 | if(history && history.replaceState && history.pushState && 57 | location.search.indexOf(query) === -1) 58 | { 59 | if(location.search === "" || forceReplace) 60 | { 61 | history.replaceState(null, document.title, "?" + query); 62 | } 63 | else 64 | { 65 | history.pushState(null, document.title, "?" + query); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/js/Preferences.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | /** 20 | * Stores user preferences using WebStorage 21 | * 22 | * Known Preferences: 23 | * - molview.theme 24 | * - sketcher.hstrip 25 | * - model.background 26 | * - messages.crystal_2d_unreliable 27 | * 28 | * @type {Object} 29 | */ 30 | var Preferences = { 31 | /** 32 | * Initialize Preferences 33 | */ 34 | init: function() 35 | { 36 | if(Storage === undefined) 37 | { 38 | window.localStorage = {}; 39 | } 40 | }, 41 | 42 | /** 43 | * Get value for Preferences key in specified module 44 | * @param {String} mod Module name (should be lowercase) 45 | * @param {String} key Key name (should be lowercase) 46 | * @param {Boolean|String} def Default value 47 | * @return {Boolean|String} Value for key in specified module 48 | */ 49 | get: function(mod, key, def) 50 | { 51 | var val = window.localStorage[mod + "." + key]; 52 | if(val === "true") return true; 53 | else if(val === "false") return false; 54 | else return val || def; 55 | }, 56 | 57 | /** 58 | * Set value for Preferences key in specified module 59 | * @param {String} mod Module name (should be lowercase) 60 | * @param {String} key Key name (should be lowercase) 61 | * @param {Boolean|String} val Value for key in module 62 | */ 63 | set: function(mod, key, val) 64 | { 65 | window.localStorage[mod + "." + key] = val; 66 | } 67 | }; 68 | -------------------------------------------------------------------------------- /src/js/chem/util/pool.js: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2009-2010 GGA Software Services LLC 3 | * 4 | * This file may be distributed and/or modified under the terms of the 5 | * GNU Affero General Public License version 3 as published by the Free 6 | * Software Foundation and appearing in the file LICENSE.GPL included in 7 | * the packaging of this file. 8 | * 9 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 10 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 11 | ***************************************************************************/ 12 | 13 | if(!window.util || !util.Map) 14 | throw new Error("Map should be defined first"); 15 | 16 | util.Pool = function () 17 | { 18 | this._map = new util.Map(); 19 | this._nextId = 0; 20 | }; 21 | 22 | util.Pool.prototype.newId = function () 23 | { 24 | return this._nextId++; 25 | }; 26 | 27 | util.Pool.prototype.add = function (obj) 28 | { 29 | var id = this._nextId++; 30 | this._map.set(id, obj); 31 | return id; 32 | }; 33 | 34 | util.Pool.prototype.set = function (id, obj) 35 | { 36 | this._map.set(id, obj); 37 | }; 38 | 39 | util.Pool.prototype.get = function (id) 40 | { 41 | return this._map.get(id); 42 | }; 43 | 44 | util.Pool.prototype.has = function (id) 45 | { 46 | return this._map.has(id); 47 | }; 48 | 49 | util.Pool.prototype.remove = function (id) 50 | { 51 | return this._map.unset(id); 52 | }; 53 | 54 | util.Pool.prototype.clear = function () 55 | { 56 | this._map.clear(); 57 | }; 58 | 59 | util.Pool.prototype.keys = function () 60 | { 61 | return this._map.keys(); 62 | }; 63 | 64 | util.Pool.prototype.ikeys = function () 65 | { 66 | return this._map.ikeys(); 67 | }; 68 | 69 | util.Pool.prototype.each = function (func, context) 70 | { 71 | this._map.each(func, context); 72 | }; 73 | 74 | util.Pool.prototype.map = function (func, context) 75 | { 76 | return this._map.map(func, context); 77 | }; 78 | 79 | util.Pool.prototype.find = function (func, context) 80 | { 81 | return this._map.find(func, context); 82 | }; 83 | 84 | util.Pool.prototype.count = function () 85 | { 86 | return this._map.count(); 87 | }; 88 | 89 | util.Pool.prototype.keyOf = function (value) 90 | { 91 | return this._map.keyOf(value); 92 | }; 93 | -------------------------------------------------------------------------------- /php/cif.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | /* 21 | PHP script for mirroring CIF files form the Crystallography Open Database 22 | 23 | @param codid 24 | @return CIF file or HTTP error 25 | */ 26 | 27 | include_once("utility.php"); 28 | 29 | error_reporting(0); 30 | parse_str($_SERVER["QUERY_STRING"]); 31 | header("Content-Type: text"); 32 | 33 | //allow embed.molview.org and molview.org 34 | $origin = $_SERVER["HTTP_ORIGIN"]; 35 | if($origin == 'http://molview.org' || $origin == 'https://embed.molview.org') 36 | { 37 | header("Access-Control-Allow-Origin: ".$origin); 38 | } 39 | 40 | //connect to cod 41 | $cod = new mysqli("www.crystallography.net", "cod_reader", "", "cod"); 42 | if($cod -> connect_errno > 0) 43 | { 44 | http_response_code(500); 45 | echo "Internal Error"; 46 | return; 47 | } 48 | 49 | //lookup record in database 50 | $query = 'SELECT flags FROM data WHERE file="'.$codid.'"'; 51 | if($row = $cod -> query($query) -> fetch_row()) 52 | { 53 | $cod -> close(); 54 | if(strpos($row[0], "has coordinates") !== false) 55 | { 56 | //get cif 57 | $cif = http_get("http://www.crystallography.net/".$codid.".cif"); 58 | if($cif === false) 59 | { 60 | http_response_code(404); 61 | echo "Not Found"; 62 | return; 63 | } 64 | else 65 | { 66 | echo $cif; 67 | return; 68 | } 69 | } 70 | else 71 | { 72 | http_response_code(404); 73 | echo "Not Found"; 74 | return; 75 | } 76 | } 77 | else 78 | { 79 | $cod -> close(); 80 | http_response_code(404); 81 | echo "Not Found"; 82 | return; 83 | } 84 | -------------------------------------------------------------------------------- /src/less/page.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "vars"; 20 | 21 | body 22 | { 23 | margin: 0; 24 | padding: 10px; 25 | 26 | color: @foreground; 27 | font-family: 'Open Sans', sans-serif; 28 | background: @light; 29 | } 30 | 31 | pre 32 | { 33 | padding: 10px; 34 | white-space: pre-wrap; 35 | background: @light2; 36 | border: 1px solid @contrast; 37 | } 38 | 39 | hr 40 | { 41 | border: 0; 42 | border-bottom: 1px solid @light2; 43 | } 44 | 45 | a 46 | { 47 | color: #06c; 48 | cursor: pointer; 49 | } 50 | 51 | a:visited 52 | { 53 | color: #06c; 54 | } 55 | 56 | a:hover 57 | { 58 | color: @highlight; 59 | text-decoration: underline; 60 | } 61 | 62 | a:active 63 | { 64 | color: @active; 65 | } 66 | 67 | #return-to-molview 68 | { 69 | display: inline-block; 70 | color: @foreground; 71 | text-decoration: none; 72 | } 73 | 74 | #header 75 | { 76 | padding-bottom: 10px; 77 | border-bottom: 1px solid @light2; 78 | font-size: 0;//remove inline-block spacing 79 | } 80 | 81 | #logo 82 | { 83 | height: 40px; 84 | } 85 | 86 | #mark 87 | { 88 | height: 40px; 89 | display: block; 90 | margin-left: 5px; 91 | vertical-align: top; 92 | } 93 | 94 | @media all and (min-width: 700px) 95 | { 96 | #logo 97 | { 98 | height: 60px; 99 | } 100 | 101 | #mark 102 | { 103 | height: 60px; 104 | margin-left: 10px; 105 | } 106 | } 107 | 108 | #content 109 | { 110 | margin: 0 auto; 111 | max-width: 700px; 112 | word-wrap: break-word; 113 | } 114 | 115 | #footer 116 | { 117 | padding: 20px 10px; 118 | text-align: center; 119 | color: @foreground-light; 120 | } 121 | -------------------------------------------------------------------------------- /src/js/molpad/Data.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | var JmolAtomColorsHashHex = { "D":"#111111","H":"#888888","He":"#849b9b","Li":"#c87efa","Be":"#82ab00","B":"#c38a8a","C":"#000000","N":"#304ff7","O":"#ff0d0d","F":"#6dab3c","Ne":"#7b9ca8","Na":"#ab5cf2","Mg":"#61b400","Al":"#a79191","Si":"#b09276","P":"#ff8000","S":"#c39517","Cl":"#1dc51d","Ar":"#63a2b0","K":"#8f40d4","Ca":"#2fc300","Sc":"#969696","Ti":"#94969a","V":"#96969a","Cr":"#8796c3","Mn":"#9c7ac7","Fe":"#e06633","Co":"#db8293","Ni":"#45b645","Cu":"#c78033","Zn":"#7d80b0","Ga":"#bd8c8c","Ge":"#668f8f","As":"#bd80e3","Se":"#e28f00","Br":"#a62929","Kr":"#53a6bc","Rb":"#702eb0","Sr":"#00d000","Y":"#5fa4a4","Zr":"#6ba2a2","Nb":"#61a4a9","Mo":"#4ea9a9","Tc":"#3b9e9e","Ru":"#248f8f","Rh":"#0a7d8c","Pd":"#006985","Ag":"#969696","Cd":"#ae9462","In":"#a67573","Sn":"#668080","Sb":"#9e63b5","Te":"#d47a00","I":"#940094","Xe":"#429eb0","Cs":"#57178f","Ba":"#00c900","La":"#57a4c5","Ce":"#989877","Pr":"#869d7b","Nd":"#7da07d","Pm":"#69a581","Sm":"#5ea883","Eu":"#43b089","Gd":"#31b48d","Tb":"#23b890","Dy":"#17bb92","Ho":"#00c578","Er":"#00c765","Tm":"#00c94e","Yb":"#00bf38","Lu":"#00ab24","Hf":"#42a8dc","Ta":"#4ba2f9","W":"#2194d6","Re":"#267dab","Os":"#266696","Ir":"#175487","Pt":"#9595a0","Au":"#b9981a","Hg":"#9595a9","Tl":"#a6544d","Pb":"#575961","Bi":"#9e4fb5","Po":"#ab5c00","At":"#754f45","Rn":"#428296","Fr":"#420066","Ra":"#007d00","Ac":"#669ce4","Th":"#00b8fc","Pa":"#00a1ff","U":"#008fff","Np":"#0080ff","Pu":"#006bff","Am":"#545cf2","Cm":"#785ce3","Bk":"#8a4fe3","Cf":"#a136d4","Es":"#b31fd4","Fm":"#B31FBA","Md":"#B30DA6","No":"#BD0D87","Lr":"#C70066","Rf":"#CC0059","Db":"#D1004F","Sg":"#D90045","Bh":"#E00038","Hs":"#E6002E","Mt":"#EB0026","Ds":"#9595a0","Rg":"#b9981a","Cn":"#9595a9" }; 20 | -------------------------------------------------------------------------------- /src/less/share.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "global"; 20 | 21 | .share 22 | { 23 | cursor: pointer; 24 | display: inline-block; 25 | position: relative; 26 | margin: 5px; 27 | overflow: hidden; 28 | 29 | .no-select; 30 | } 31 | 32 | .share:hover > span:after 33 | { 34 | opacity: 1; 35 | } 36 | 37 | .share > span 38 | { 39 | display: inline-block; 40 | position: relative; 41 | padding: 10px; 42 | min-width: 100px; 43 | 44 | color: #fff; 45 | font-size: 16pt; 46 | text-align: center; 47 | background: rgba(0, 0, 0, 0.2); 48 | 49 | border-radius: 0 4px 4px 0; 50 | } 51 | 52 | .share-twitter, .share-twitter > span:after 53 | { background: #55acee; } 54 | .share-facebook, .share-facebook > span:after 55 | { background: #3b5999; } 56 | .share-googleplus, .share-googleplus > span:after 57 | { background: #d34836; } 58 | 59 | .share:before 60 | { 61 | display: inline-block; 62 | left: 0; 63 | width: 48px; 64 | vertical-align: sub; 65 | 66 | font-family: FontAwesome; 67 | font-size: 22pt; 68 | text-align: center; 69 | color: #fff; 70 | } 71 | 72 | .share > span:after 73 | { 74 | display: block; 75 | position: absolute; 76 | top: 0; 77 | right: 0; 78 | width: 100%; 79 | height: 100%; 80 | 81 | color: #fff; 82 | font-size: 20pt; 83 | text-align: center; 84 | line-height: 48px; 85 | opacity: 0; 86 | 87 | border-radius: 0 4px 4px 0; 88 | } 89 | 90 | .share-facebook:before 91 | { content: '\f09a'; } 92 | .share-twitter:before 93 | { content: '\f099'; } 94 | .share-googleplus:before 95 | { content: '\f0d5'; } 96 | 97 | .share-facebook span:after 98 | { content: 'Share'; } 99 | .share-twitter span:after 100 | { content: 'Tweet'; } 101 | .share-googleplus span:after 102 | { content: '+1'; } 103 | -------------------------------------------------------------------------------- /src/js/molpad/MPLine.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | function MPLine(obj) 20 | { 21 | this.from = obj !== undefined ? obj.from.clone() || new MPPoint() : new MPPoint(); 22 | this.to = obj !== undefined ? obj.to.clone() || new MPPoint() : new MPPoint(); 23 | } 24 | 25 | /* function lineLineIntersection(x1, y1, x2, y2, x3, y3, x4, y4) 26 | { 27 | var div = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); 28 | return { 29 | x: ((x1 * y2 - y1 * x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3 * x4)) / div, 30 | y: ((x1 * y2 - y1 * x2) * (y3 - y4) - (y1 - y2) * (x3 * y4 - y3 * x4)) / div 31 | }; 32 | } */ 33 | 34 | MPLine.prototype.intersection = function(line) 35 | { 36 | var denominator = ((line.to.y - line.from.y) * (this.to.x - this.from.x)) 37 | - ((line.to.x - line.from.x) * (this.to.y - this.from.y)); 38 | 39 | if(denominator === 0) 40 | { 41 | return { 42 | p: undefined, 43 | onL1: false, 44 | onL2: false 45 | }; 46 | } 47 | 48 | var a = this.from.y - line.from.y; 49 | var b = this.from.x - line.from.x; 50 | var numerator1 = ((line.to.x - line.from.x) * a) - ((line.to.y - line.from.y) * b); 51 | var numerator2 = ((this.to.x - this.from.x) * a) - ((this.to.y - this.from.y) * b); 52 | a = numerator1 / denominator; 53 | b = numerator2 / denominator; 54 | 55 | return { 56 | p: MPPFO({ 57 | x: this.from.x + (a * (this.to.x - this.from.x)), 58 | y: this.from.y + (a * (this.to.y - this.from.y)) 59 | }), 60 | //if line2 is a segment and line1 is infinite, they intersect if 61 | onL1: a > 0 && a < 1, 62 | //if line2 is a segment and line1 is infinite, they intersect if: 63 | onL2: b > 0 && b < 1 64 | }; 65 | } 66 | 67 | MPLine.prototype.length = function() 68 | { 69 | return this.from.distanceTo(this.to); 70 | } 71 | -------------------------------------------------------------------------------- /src/less/active.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "form"; 20 | @import (reference) "autocomplete"; 21 | 22 | /* 23 | form 24 | */ 25 | .input-wrapper > button:active 26 | { 27 | color: @active; 28 | } 29 | 30 | .btn:active 31 | { 32 | .form-box-active; 33 | } 34 | 35 | .close-btn:active, .dialog-close-btn:active 36 | { 37 | color: #f00; 38 | } 39 | 40 | /* 41 | menu 42 | */ 43 | .dropdown-toggle:not(.tool-button-disabled):active 44 | { 45 | background-color: @light !important; 46 | border-color: @contrast !important; 47 | } 48 | 49 | .menu-item > a:not(.disabled):active 50 | { 51 | background-color: @light3; 52 | } 53 | 54 | #layout-menu > a:active 55 | { 56 | opacity: 1.0; 57 | background-color: @light3; 58 | } 59 | 60 | /* 61 | sketcher 62 | */ 63 | .tool-button:not(.tool-button-disabled):active 64 | { 65 | background-color: @highlight-light; 66 | } 67 | 68 | #chem-tools > .toolbar-inner > .tool-button:not(.tool-button-disabled):active 69 | { 70 | border-right: 3px solid @highlight; 71 | width: 37px; 72 | } 73 | 74 | #elem-tools > .toolbar-inner > .tool-button:not(.tool-button-disabled):active 75 | { 76 | border-left: 3px solid @highlight; 77 | width: 37px; 78 | } 79 | 80 | #edit-tools > .toolbar-inner > .tool-button:not(.tool-button-disabled):active 81 | { 82 | border-bottom: 3px solid @highlight; 83 | height: 37px; 84 | } 85 | 86 | /* periodictable */ 87 | .pt-element:active 88 | { 89 | background-color: @highlight-light; 90 | border-color: @highlight; 91 | } 92 | 93 | /* 94 | help 95 | */ 96 | .expandable-title:active 97 | { 98 | background: @contrast; 99 | } 100 | 101 | /* 102 | search 103 | */ 104 | .search-result-title:active, .search-result-pubchem:active > .search-result-title, .load-more:active 105 | { 106 | background: @light2; 107 | } 108 | 109 | .load-more:active 110 | { 111 | border-color: @contrast; 112 | } 113 | 114 | 115 | /* 116 | autocomplete 117 | */ 118 | .autocomplete-item:active 119 | { 120 | .autocomplete-item-active; 121 | } 122 | 123 | /* 124 | messages 125 | */ 126 | .message-close-btn:active 127 | { 128 | background: rgba(0, 0, 0, 0.5); 129 | } 130 | -------------------------------------------------------------------------------- /src/js/MolView.Embed.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | /** 20 | * Lightweight MolView variant for /embed 21 | * @type {Object} 22 | */ 23 | var MolView = { 24 | touch: false, 25 | mobile: false, 26 | devicePixelRatio: 1.0, 27 | trigger: "click", 28 | query: {}, 29 | loadDefault: true, 30 | JMOL_J2S_PATH: "jmol/j2s", 31 | 32 | 33 | init: function() 34 | { 35 | MolView.devicePixelRatio = window.devicePixelRatio || (MolView.mobile ? 1.5 : 1.0); 36 | 37 | this.query = getQuery(); 38 | Model.preloadQuery(this.query); 39 | if(this.query.q || this.query.smiles || this.query.cid || this.query.pdbid || this.query.codid) 40 | { 41 | this.loadDefault = false; 42 | } 43 | 44 | Progress.init(); 45 | if(this.loadDefault) 46 | { 47 | Progress.reset(2); 48 | } 49 | 50 | //initialize 51 | Request.init(); 52 | 53 | $(window).on("resize", Model.resize.bind(Model)); 54 | 55 | Progress.increment(); 56 | 57 | if(this.touch && !Detector.webgl) 58 | { 59 | Model.JSmol.setQuality(false); 60 | } 61 | 62 | Model.init((function() 63 | { 64 | $.each(this.query, function(key, value) 65 | { 66 | if(key === "smiles") 67 | { 68 | Messages.process(function() 69 | { 70 | Loader.loadSMILES(value, document.title); 71 | }, "compound"); 72 | } 73 | else if(key === "cid") 74 | { 75 | Loader.PubChem.loadCID(value, document.title); 76 | } 77 | else if(key === "pdbid") 78 | { 79 | Loader.RCSB.loadPDBID(value, value.toUpperCase()); 80 | } 81 | else if(key === "codid") 82 | { 83 | Loader.COD.loadCODID(value, document.title); 84 | } 85 | else if(key === "bg") 86 | { 87 | Model.setBackground(value); 88 | } 89 | }); 90 | 91 | if(!(this.query.smiles || this.query.cid || this.query.pdbid || this.query.codid)) 92 | { 93 | Progress.complete(); 94 | } 95 | }).bind(this), Detector.webgl ? "GLmol" : (((this.query.pdbid && !MolView.mobile) || this.query.codid) ? "JSmol" : "GLmol")); 96 | }, 97 | 98 | //do not remove: called from Loader 99 | makeModelVisible: function() 100 | { 101 | }, 102 | }; 103 | 104 | $(document).on("ready", function() 105 | { 106 | MolView.init(); 107 | }); 108 | -------------------------------------------------------------------------------- /src/less/global.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "vars"; 20 | 21 | h3 22 | { 23 | margin: 25px 0 5px 0; 24 | } 25 | 26 | h4 27 | { 28 | margin: 20px 0 0 0; 29 | } 30 | 31 | p 32 | { 33 | margin: 5px 0; 34 | } 35 | 36 | h4 + p 37 | { 38 | margin: 0 0 5px 0; 39 | } 40 | 41 | li 42 | { 43 | margin: 10px 0; 44 | } 45 | 46 | img 47 | { 48 | display: block; 49 | max-width: 100%; 50 | } 51 | 52 | table 53 | { 54 | border-spacing: 0; 55 | } 56 | 57 | a 58 | { 59 | cursor: pointer; 60 | text-decoration: none; 61 | } 62 | 63 | a.link 64 | { 65 | cursor: pointer; 66 | color: @linkcolor; 67 | border-bottom: 0px solid @highlight; 68 | transition: border .1s linear; 69 | } 70 | 71 | a.link:hover 72 | { 73 | color: @highlight; 74 | text-decoration: underline; 75 | } 76 | 77 | a.link:active 78 | { 79 | color: @active; 80 | } 81 | 82 | a.a 83 | { 84 | color: inherit; 85 | cursor: pointer; 86 | text-decoration: none; 87 | } 88 | 89 | a.a:visited 90 | { 91 | color: @foreground-disabled; 92 | } 93 | 94 | a.a:hover 95 | { 96 | color: @highlight; 97 | text-decoration: underline; 98 | } 99 | 100 | a.a:active 101 | { 102 | color: @active; 103 | } 104 | 105 | a.gray 106 | { 107 | color: @foreground-lighter; 108 | cursor: pointer; 109 | } 110 | 111 | a.gray:visited 112 | { 113 | color: @foreground-lighter; 114 | } 115 | 116 | a.gray:hover 117 | { 118 | color: @foreground-aside; 119 | text-decoration: underline; 120 | } 121 | 122 | a.gray:active 123 | { 124 | color: @foreground-less; 125 | } 126 | 127 | .no-select 128 | { 129 | -webkit-user-select: none; 130 | -khtml-user-select: none; 131 | -moz-user-select: none; 132 | -o-user-select: none; 133 | user-select: none; 134 | } 135 | 136 | .progress-cursor 137 | { 138 | cursor: progress; 139 | } 140 | 141 | .alert-bar 142 | { 143 | display: block; 144 | margin: 5px 5px 10px 5px; 145 | padding: 10px; 146 | 147 | background: @error-light; 148 | border-left: 4px solid @error; 149 | } 150 | 151 | .hstack 152 | { 153 | font-size: 0 !important; 154 | white-space: nowrap; 155 | } 156 | 157 | .hstack > * 158 | { 159 | display: inline-block; 160 | vertical-align: top; 161 | font-size: normal; 162 | font-size: initial; 163 | } 164 | -------------------------------------------------------------------------------- /src/js/Link.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | /** 20 | * Share/embed dialog wrapper 21 | * @type {Object} 22 | */ 23 | var Link = { 24 | embedHTML: "", 25 | 26 | init: function() 27 | { 28 | $("#embed-width, #embed-height").on("keyup", this.updateEmbedDialog); 29 | }, 30 | 31 | updateShareDialog: function() 32 | { 33 | if($("#action-resolve").hasClass("resolve-outdated") && MolView.layout !== "model") $("#share-2d-not-3d").show(); 34 | else $("#share-2d-not-3d").hide(); 35 | 36 | var url = window.location.origin + window.location.pathname; 37 | var msg = ""; 38 | 39 | if(Loader.lastQuery.type !== "") 40 | { 41 | msg = "Cool structure on MolView!"; 42 | url += "?" + Loader.lastQuery.type + "=" + specialEncodeURIComponent(Loader.lastQuery.content.replace(/^ /, "")); 43 | } 44 | 45 | $("#share-link").val(url); 46 | $("#share-dialog .social").share({ all: url }, false, msg); 47 | }, 48 | 49 | updateEmbedDialog: function() 50 | { 51 | if($("#action-resolve").hasClass("resolve-outdated") && MolView.layout !== "model") $("#embed-2d-not-3d").show(); 52 | else $("#embed-2d-not-3d").hide(); 53 | 54 | var url = "https://embed.molview.org/v1/?mode=" + Model.representation; 55 | 56 | if(oneOf(Loader.lastQuery.type, ["smiles", "cid", "pdbid", "codid"])) 57 | { 58 | url += "&" + Loader.lastQuery.type + "=" + specialEncodeURIComponent(Loader.lastQuery.content.replace(/^ /, "")); 59 | } 60 | 61 | if(Model.bg.colorName !== "black") 62 | { 63 | url += "&bg=" + Model.bg.colorName; 64 | } 65 | 66 | if(Model.isPDB()) 67 | { 68 | if(Model.chain.type === "ribbon" || Model.chain.type === "cylinders" 69 | || Model.chain.type === "btube" || Model.chain.type === "ctrace") 70 | { 71 | url += "&chainType=" + Model.chain.type; 72 | } 73 | if(Model.chain.bonds) 74 | { 75 | if(Model.chain.type === "none") 76 | { 77 | url += "&chainType=bonds"; 78 | } 79 | else 80 | { 81 | url += "&chainBonds=true" 82 | } 83 | } 84 | if(Model.chain.color) 85 | { 86 | url += "&chainColor=" + Model.chain.color; 87 | } 88 | } 89 | 90 | Link.embedHTML = ''; 91 | $("#embed-code").val(Link.embedHTML); 92 | $("#embed-url").val(url); 93 | } 94 | }; 95 | -------------------------------------------------------------------------------- /src/less/layout.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "vars"; 20 | @import (reference) "global"; 21 | 22 | html 23 | { 24 | overflow: hidden; 25 | } 26 | 27 | body 28 | { 29 | position: absolute; 30 | margin: 0; 31 | padding: 0; 32 | width: 100%; 33 | height: 100%; 34 | 35 | color: @foreground; 36 | font-family: 'Open Sans', sans-serif; 37 | background: @light; 38 | overflow: hidden; 39 | } 40 | 41 | #progress 42 | { 43 | z-index: 2; 44 | position: absolute; 45 | top: 0; 46 | left: 0; 47 | right: 0; 48 | height: 3px; 49 | } 50 | 51 | #progress-canvas 52 | { 53 | position: absolute; 54 | } 55 | 56 | #menu 57 | { 58 | z-index: 1; 59 | position: absolute; 60 | top: 0; 61 | left: 0; 62 | right: 0; 63 | height: @menubar-height; 64 | } 65 | 66 | .no-menu > #menu 67 | { 68 | display: none; 69 | } 70 | 71 | .no-menu > #progress 72 | { 73 | top: 0; 74 | } 75 | 76 | .no-menu > #content 77 | { 78 | top: 0; 79 | } 80 | 81 | #content 82 | { 83 | position: absolute; 84 | top: @menubar-height + 1; 85 | left: 0; 86 | right: 0; 87 | bottom: 0; 88 | } 89 | 90 | .layer 91 | { 92 | position: absolute; 93 | top: 0; 94 | left: 0; 95 | right: 0; 96 | bottom: 0; 97 | } 98 | 99 | #sketcher 100 | { 101 | position: absolute; 102 | top: 0; 103 | left: 0; 104 | right: 50%; 105 | bottom: 0; 106 | background: #eee; 107 | } 108 | 109 | .layout-sketcher > #sketcher, .layout-hsplit > #sketcher 110 | { right: 0; } 111 | 112 | .layout-hsplit > #sketcher 113 | { bottom: 50%; } 114 | 115 | .layout-model > #sketcher 116 | { visibility: hidden; } 117 | 118 | #model 119 | { 120 | position: absolute; 121 | top: 0; 122 | left: 50%; 123 | right: 0; 124 | bottom: 0; 125 | background: #000; 126 | overflow: hidden; 127 | } 128 | 129 | .layout-model > #model, .layout-hsplit > #model 130 | { left: 0; } 131 | 132 | .layout-hsplit > #model 133 | { top: 50%; } 134 | 135 | .layout-sketcher > #model 136 | { visibility: hidden; } 137 | 138 | #messages 139 | { 140 | z-index: 3; 141 | } 142 | 143 | #dialog-overlay 144 | { 145 | z-index: 4; 146 | } 147 | 148 | #about-links 149 | { 150 | margin-top: 50px; 151 | text-align: center; 152 | line-height: 2; 153 | color: @foreground-light; 154 | } 155 | 156 | #share-dialog-social 157 | { 158 | margin: 5px 0 5px -5px; 159 | } 160 | -------------------------------------------------------------------------------- /src/svg/action/hstrip.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | image/svg+xml -------------------------------------------------------------------------------- /src/less/chemicaldata.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "vars"; 20 | 21 | .data-layer 22 | { 23 | margin: 0; 24 | padding: 10px; 25 | background: @light; 26 | overflow: auto; 27 | } 28 | 29 | #infocard-layer 30 | { 31 | padding-bottom: 100px; 32 | text-align: center; 33 | } 34 | 35 | #properties-wrapper 36 | { 37 | display: inline-block; 38 | max-width: 600px; 39 | width: 100%; 40 | } 41 | 42 | #general-properties 43 | { 44 | text-align: center; 45 | font-size: 0; 46 | } 47 | 48 | #properties-wrapper > div:last-child 49 | { 50 | margin-bottom: 100px; 51 | } 52 | 53 | .properties-block 54 | { 55 | position: relative; 56 | display: block; 57 | margin: 0; 58 | font-size: medium; 59 | font-size: initial; 60 | text-align: left; 61 | width: 100%; 62 | } 63 | 64 | .properties-block table 65 | { 66 | width: 100%; 67 | } 68 | 69 | @media all and (min-width: 1200px) 70 | { 71 | #properties-wrapper 72 | { 73 | margin: 0; 74 | width: auto; 75 | max-width: 1100px; 76 | } 77 | 78 | #general-properties 79 | { 80 | margin: -10px; 81 | padding-bottom: 10px; 82 | 83 | /* in order to fit the image and primary table 84 | together ([space] between blocks = 0) */ 85 | font-size: 0; 86 | } 87 | 88 | .properties-block 89 | { 90 | display: inline-block; 91 | margin: 10px; 92 | width: 539px; 93 | vertical-align: middle; 94 | } 95 | } 96 | 97 | @media all and (min-width: 1300px) 98 | { 99 | #properties-wrapper 100 | { 101 | max-width: 1200px; 102 | } 103 | 104 | .properties-block 105 | { 106 | width: 589px; 107 | } 108 | } 109 | 110 | #molecule-image 111 | { 112 | margin: 0 auto; 113 | } 114 | 115 | #molecule-info 116 | { 117 | padding: 15px 10px; 118 | } 119 | 120 | #molecule-title 121 | { 122 | margin: 0; 123 | } 124 | 125 | #spectrum-wrapper 126 | { 127 | overflow: auto; 128 | } 129 | 130 | /* 131 | Chemprops 132 | */ 133 | 134 | .chemprop-loading 135 | { 136 | cursor: progress; 137 | background-image: url(../img/misc/spinner.svg); 138 | background-size: 24px; 139 | background-repeat: no-repeat; 140 | background-position: center; 141 | } 142 | 143 | .chem-identifier 144 | { 145 | text-align: left; 146 | } 147 | 148 | .chem-identifier > label 149 | { 150 | display: inline-block; 151 | margin-top: 10px; 152 | padding: 5px; 153 | font-weight: bold; 154 | } 155 | 156 | .chem-link 157 | { 158 | padding: 0 5px; 159 | } 160 | -------------------------------------------------------------------------------- /src/svg/action/rotate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 52 | 55 | 58 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/less/hover.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "form"; 20 | @import (reference) "autocomplete"; 21 | 22 | /* 23 | form 24 | */ 25 | .input-wrapper > button:hover 26 | { 27 | color: @highlight; 28 | } 29 | 30 | /* input:not([disabled])[type="text"]:hover + .input-focus 31 | { 32 | background: @foreground-less; 33 | } 34 | 35 | .input:hover 36 | { 37 | border-color: @foreground; 38 | } */ 39 | 40 | .btn:hover 41 | { 42 | .form-box-hover; 43 | } 44 | 45 | .close-btn:hover, .dialog-close-btn:hover 46 | { 47 | color: #f50; 48 | } 49 | 50 | /* 51 | menu 52 | */ 53 | .dropdown-toggle:hover 54 | { 55 | background-color: @light2 !important; 56 | border-color: @contrast !important; 57 | } 58 | 59 | .menu-item > a:not(.disabled):hover 60 | { 61 | background-color: @light2; 62 | } 63 | 64 | #layout-menu > a:hover 65 | { 66 | opacity: 0.9; 67 | background-color: @light2; 68 | } 69 | 70 | .menu-item > a.radio:hover:before, .menu-item > a.check:hover:before 71 | { 72 | color: @foreground-light; 73 | } 74 | 75 | /* 76 | sketcher 77 | */ 78 | .tool-button:not(.tool-button-disabled):hover 79 | { 80 | background-color: @light3; 81 | } 82 | 83 | #chem-tools > .toolbar-inner > .tool-button:not(.tool-button-disabled):hover 84 | { 85 | border-right: 3px solid @foreground-less; 86 | width: 37px; 87 | } 88 | 89 | #elem-tools > .toolbar-inner > .tool-button:not(.tool-button-disabled):hover 90 | { 91 | border-left: 3px solid @foreground-less; 92 | width: 37px; 93 | } 94 | 95 | #edit-tools > .toolbar-inner > .tool-button:not(.tool-button-disabled):hover 96 | { 97 | border-bottom: 3px solid @foreground-less; 98 | height: 37px; 99 | } 100 | 101 | /* 102 | periodictable 103 | */ 104 | .pt-element:hover 105 | { 106 | background: @light2; 107 | } 108 | 109 | /* 110 | help 111 | */ 112 | .expandable-title:hover 113 | { 114 | background: @light2; 115 | } 116 | 117 | /* 118 | search 119 | */ 120 | .search-result-title:hover, .search-result-pubchem:hover > .search-result-title 121 | { 122 | color: @linkcolor; 123 | } 124 | 125 | .search-result-title:hover > span, .search-result-pubchem:hover > .search-result-title > span 126 | { 127 | border-bottom: 2px solid; 128 | } 129 | 130 | .load-more:hover 131 | { 132 | background: @light; 133 | } 134 | 135 | .load-more:hover 136 | { 137 | border-color: @contrast; 138 | } 139 | 140 | /* 141 | autocomplete 142 | */ 143 | .autocomplete-item:hover 144 | { 145 | .autocomplete-item-hover; 146 | } 147 | 148 | /* 149 | messages 150 | */ 151 | .message-close-btn:hover 152 | { 153 | background: rgba(0, 0, 0, 0.4); 154 | } 155 | -------------------------------------------------------------------------------- /LEGAL.md: -------------------------------------------------------------------------------- 1 | Terms of Use 2 | ============ 3 | Welcome to MolView! 4 | These are the Terms of Use ("Terms") of molview.org ("This Site", "MolView") 5 | This site contains the latest stable release of the MolView Open-Source Project 6 | ("The MolView Open-Source Project", "The MolView Project") 7 | 8 | By accessing and using this site, you accept and agree to be bound by the terms 9 | and provision of this agreement. 10 | 11 | ANY PARTICIPATION IN THIS SITE WILL CONSTITUTE ACCEPTANCE OF THESE TERMS. 12 | IF YOU DO NOT AGREE TO ABIDE BY THE ABOVE, PLEASE DO NOT USE THIS SITE. 13 | 14 | THIS SITE RESERVES THE RIGHT TO UPDATE OR AMEND THE TERMS AT ANY TIME WITHOUT 15 | NOTICE TO YOU. SUCH UPDATED OR AMENDED TERMS SHALL BE EFFECTIVE UPON PUBLISHING 16 | ON THIS SITE. 17 | 18 | ## 1. Copyright 19 | MolView and The MolView Project are copyright of Herman Bergwerf. 20 | The MolView Project is Open-Source and the source code is released under the 21 | GNU AGPL license. All MolView redistributions are subject to 22 | The MolView Open-Source Project and it's respective license. 23 | You can find the latest MolView Project source release at: 24 | https://github.com/molview 25 | 26 | ## 2. Site Content 27 | This site is frequently updated with new releases from the MolView Project. 28 | 29 | THIS SITE RESERVES THE RIGHT TO CHANGE OR UPDATE IT'S SITE CONTENT 30 | FOR ANY REASON AT ANY TIME WITHOUT NOTICE TO YOU. 31 | 32 | THIS SITE RESERVES THE RIGHT TO TERMINATE OR RESTRICT THE ACCESS OR USE OF 33 | THIS SITE FOR ANY REASON AT ANY TIME WITHOUT NOTICE TO YOU. 34 | 35 | ## 3. Accuracy of Information 36 | Some of the data contained in MolView is, directly or indirectly, retrieved from 37 | remote third-party data sources. Therefore, MolView does not warrant that the 38 | data which is made available in it's site is accurate. 39 | 40 | THIS SITE DOES NOT WARRANT THAT ANY INFORMATION TRANSMITTED OR MADE AVAILABLE IN 41 | ITS SITE IS COMPLETE AND CORRECT OR FIT FOR ANY PARTICULAR PURPOSE AND SHALL NOT 42 | BE RESPONSIBLE OR LIABLE WHATSOEVER FOR ANY ERROR OR OMISSIONS IN THAT 43 | INFORMATION OR ANY DAMAGES INCURRED AS A RESULT OF ITS USE. 44 | 45 | ## 4. Intellectual Property Rights 46 | If you own the copyright of any of the data transmitted or made available in 47 | this site and you want it to be removed, please contact 48 | so we can resolve this as soon as possible. 49 | 50 | ALL DATA TRANSMITTED OR MADE AVAILABLE IN THIS SITE IS BELIEVED TO BE FREE OF 51 | INFRINGEMENT, PLEASE CONTACT IF YOU CAN PROVE OTHERWISE. 52 | 53 | THIS SITE DOES NOT OWN THE COPYRIGHT OR INTELLECTUAL PROPERTY RIGHTS OF THE 54 | THIRD-PARTY DATA CONTAINED IN ITS SITE AND DOES NOT WARRANT FOR ANY KIND OF 55 | INFRINGEMENT AS A RESULT OF ITS USE. 56 | 57 | ## 5. Privacy Policy 58 | This site does not store any personal information on it's own server. 59 | 60 | This sites uses Google Analytics in order to collect usage data. 61 | This service is subject to the Google Analytics Terms of Service 62 | which can be found at: https://www.google.com/analytics/terms/us.html 63 | 64 | This site uses a client-side local storage technology (WebStorage) 65 | in order to save user preferences. You can find the full specification of this 66 | technology by W3C at: http://www.w3.org/TR/webstorage/ 67 | This local data storage relies on your browser. This site does not warrant that 68 | any of the information which is saved in this local data storage is correct or 69 | will be retained by your browser. 70 | -------------------------------------------------------------------------------- /page.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | include_once("php/Parsedown.php"); 21 | include_once("php/utility.php"); 22 | 23 | error_reporting(0); 24 | parse_str($_SERVER["QUERY_STRING"]); 25 | 26 | $map = array( 27 | "readme" => "README.md", 28 | "changelog" => "CHANGELOG.md", 29 | "license" => "LICENSE.md", 30 | "legal" => "LEGAL.md", 31 | "iesupport" => "pages/iesupport.md", 32 | "htmlcanvas" => "pages/htmlcanvas.md", 33 | "tracking" => "pages/tracking.md", 34 | "400" => "pages/400.md", 35 | "401" => "pages/401.md", 36 | "403" => "pages/403.md", 37 | "404" => "pages/404.md", 38 | "500" => "pages/500.md" 39 | ); 40 | 41 | $titleMap = array( 42 | "readme" => "README", 43 | "changelog" => "Changelog", 44 | "license" => "License", 45 | "legal" => "Legal", 46 | "iesupport" => "No support", 47 | "htmlcanvas" => "No support", 48 | "tracking" => "Event tracking", 49 | "400" => "Bad request", 50 | "401" => "Authorization required", 51 | "403" => "Forbidden", 52 | "404" => "Not found", 53 | "500" => "Internal server error" 54 | ); 55 | 56 | $copyrightMap = array( 57 | "readme" => false, 58 | "changelog" => false, 59 | "license" => true, 60 | "legal" => true, 61 | "iesupport" => false, 62 | "htmlcanvas" => false, 63 | "tracking" => false, 64 | "400" => false, 65 | "401" => false, 66 | "403" => false, 67 | "404" => false, 68 | "500" => false 69 | ); 70 | 71 | $md = file_get_contents($map[$id]); 72 | $renderer = new Parsedown(); 73 | ?> 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | ".$titleMap[$id].""; ?> 83 | 84 | /> 85 | 86 | 87 | 88 | /> 89 | 90 | 91 | 97 |
98 | text($md); ?> 99 |
100 | Copyright © 2014, 2015 Herman Bergwerf'; ?> 101 | 102 | 103 | -------------------------------------------------------------------------------- /src/js/Share.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | //jQuery plugin 20 | $.fn.share = function(url, display_count, message) 21 | { 22 | var default_msg = "View chemical structures using this free webapp!"; 23 | 24 | this.children().each(function() 25 | { 26 | if($(this).hasClass("share-facebook")) 27 | { 28 | var self = $(this); 29 | self.empty().unbind(); 30 | 31 | if(display_count) 32 | { 33 | AJAX({ 34 | url: "https://api.facebook.com/method/fql.query?query=" + encodeURIComponent("select total_count from link_stat where url='" + (url.fb || url.all) + "'") + "&format=json&callback=?", 35 | dataType: "jsonp", 36 | success: function(data) 37 | { 38 | self.data("total_count", data[0].total_count); 39 | $("").html("" + data[0].total_count + " Likes") 40 | .appendTo(self); 41 | } 42 | }); 43 | } 44 | else $("").html("Facebook").appendTo(self); 45 | 46 | self.on("click", function() 47 | { 48 | window.open("https://www.facebook.com/sharer/sharer.php?u=" + encodeURIComponent(url.fb || url.all)); 49 | }); 50 | } 51 | else if($(this).hasClass("share-twitter")) 52 | { 53 | var self = $(this); 54 | self.empty().unbind(); 55 | 56 | if(display_count) 57 | { 58 | AJAX({ 59 | url: "http://cdn.api.twitter.com/1/urls/count.json?url=" + encodeURIComponent(url.twitter || url.all) + "&callback=?", 60 | dataType: "jsonp", 61 | success: function(data) 62 | { 63 | self.data("count", data.count); 64 | $("").html("" + data.count + " Tweets") 65 | .appendTo(self); 66 | } 67 | }); 68 | } 69 | else $("").html("Twitter").appendTo(self); 70 | 71 | self.on("click", function() 72 | { 73 | window.open("https://twitter.com/intent/tweet?text=" + encodeURIComponent(message || default_msg) + "&url=" + encodeURIComponent(url.twitter || url.all) + "&via=molview"); 74 | }); 75 | } 76 | else if($(this).hasClass("share-googleplus")) 77 | { 78 | var self = $(this); 79 | self.empty().unbind(); 80 | 81 | if(display_count) 82 | { 83 | AJAX({ 84 | url: "api/gplus?url=" + encodeURIComponent(url.gplus || url.all), 85 | dataType: "json", 86 | success: function(data) 87 | { 88 | self.data("count", data.count); 89 | $("").html("" + data.count + " +1's") 90 | .appendTo(self); 91 | } 92 | }); 93 | } 94 | else $("").html("Google+").appendTo(self); 95 | 96 | self.on("click", function() 97 | { 98 | window.open("https://plus.google.com/share?hl=en-US&url=" + encodeURIComponent(url.gplus || url.all)); 99 | }) 100 | } 101 | }); 102 | }; 103 | -------------------------------------------------------------------------------- /embed.php: -------------------------------------------------------------------------------- 1 | isMobile() || $detect -> isTablet(); 9 | 10 | //preserve + sign by encoding it to %2B before parsing it 11 | parse_str(str_replace("+", "%2B", $_SERVER["QUERY_STRING"])); 12 | ?> 13 | 14 | 15 | 16 | 17 | 34 | 35 | 56 | 57 | 58 | 59 | 60 | 61 | MolView 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 82 | 83 | > 90 | 91 | 92 | 93 |
94 | 95 | 96 | -------------------------------------------------------------------------------- /src/js/chem/util/map.js: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2009-2010 GGA Software Services LLC 3 | * 4 | * This file may be distributed and/or modified under the terms of the 5 | * GNU Affero General Public License version 3 as published by the Free 6 | * Software Foundation and appearing in the file LICENSE.GPL included in 7 | * the packaging of this file. 8 | * 9 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 10 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 11 | ***************************************************************************/ 12 | 13 | if(!window.util) 14 | util = {}; 15 | 16 | util.Map = function (obj) 17 | { 18 | if(typeof (obj) !== 'undefined' && obj.constructor !== Object) 19 | throw Error("Passed object is not an instance of 'Object'!"); 20 | this._obj = obj || 21 | {}; 22 | this._count = 0; 23 | }; 24 | 25 | util.Map.prototype.each = function (func, context) 26 | { 27 | for(var v in this._obj) 28 | { 29 | var v_int = parseInt(v); 30 | var value = this._obj[v]; 31 | 32 | if(!isNaN(v_int)) 33 | v = v_int; 34 | func.call(context, v, value) 35 | } 36 | }; 37 | 38 | util.Map.prototype.map = function (func, context) 39 | { 40 | var ret = new util.Map(); 41 | this.each(function (v, value) 42 | { 43 | ret.set(v, func.call(context, v, value)); 44 | }, this); 45 | return ret; 46 | }; 47 | 48 | util.Map.prototype.find = function (func, context) 49 | { 50 | for(var v in this._obj) 51 | { 52 | var v_int = parseInt(v); 53 | var value = this._obj[v]; 54 | 55 | if(!isNaN(v_int)) 56 | v = v_int; 57 | if(func.call(context, v, value)) 58 | return v; 59 | } 60 | }; 61 | 62 | util.Map.prototype.findAll = function (func, context) 63 | { 64 | var vv = []; 65 | for(var v in this._obj) 66 | { 67 | var v_int = parseInt(v); 68 | var value = this._obj[v]; 69 | if(!isNaN(v_int)) 70 | v = v_int; 71 | if(func.call(context, v, value)) 72 | vv.push(v); 73 | } 74 | return vv; 75 | }; 76 | 77 | util.Map.prototype.keys = function () 78 | { 79 | var keys = []; 80 | for(var v in this._obj) 81 | { 82 | keys.push(v); 83 | } 84 | return keys; 85 | }; 86 | 87 | util.Map.prototype.ikeys = function () 88 | { 89 | var keys = []; 90 | for(var v in this._obj) 91 | { 92 | keys.push(v - 0); 93 | } 94 | return keys; 95 | }; 96 | 97 | util.Map.prototype.set = function (key, value) 98 | { 99 | this._count += (typeof (value) !== 'undefined' ? 1 : 0) - (typeof (this._obj[key]) !== 'undefined' ? 1 : 0); 100 | if(typeof (value) === 'undefined') 101 | { 102 | var val = this._obj[key]; 103 | delete this._obj[key]; 104 | return val; 105 | } 106 | else 107 | { 108 | return this._obj[key] = value; 109 | } 110 | }; 111 | 112 | util.Map.prototype.get = function (key) 113 | { 114 | if(this._obj[key] !== Object.prototype[key]) 115 | return this._obj[key]; 116 | return undefined; 117 | }; 118 | 119 | util.Map.prototype.has = function (key) 120 | { 121 | return(this._obj[key] !== Object.prototype[key]); 122 | }; 123 | 124 | util.Map.prototype.unset = function (key) 125 | { 126 | return this.set(key, undefined); 127 | }; 128 | 129 | util.Map.prototype.update = function (object) 130 | { 131 | for(var v in object) 132 | this.set(v, object[v]); 133 | }; 134 | 135 | util.Map.prototype.clear = function () 136 | { 137 | this._obj = {}; 138 | this._count = 0; 139 | }; 140 | 141 | util.Map.prototype.count = function () 142 | { 143 | return this._count; 144 | }; 145 | 146 | util.Map.prototype.idList = function () 147 | { 148 | return util.idList(this._obj); 149 | }; 150 | 151 | util.Map.prototype.keyOf = function (value) 152 | { 153 | for(var key in this._obj) 154 | if(this._obj[key] === value) return key; 155 | }; 156 | -------------------------------------------------------------------------------- /src/less/menu-theme.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "vars"; 20 | 21 | #brand 22 | { 23 | width: 50px; 24 | height: 40px; 25 | background-image: url(../img/brand.svg); 26 | background-repeat: no-repeat; 27 | background-position: center; 28 | } 29 | 30 | .dropdown-toggle 31 | { 32 | border-left: 1px solid @menu-bar-bg; 33 | border-right: 1px solid @menu-bar-bg; 34 | } 35 | 36 | .dropdown-toggle:after 37 | { 38 | margin-left: 8px; 39 | color: @foreground; 40 | font-family: FontAwesome; 41 | content: '\f107'; 42 | } 43 | 44 | .dropdown.open > .dropdown-toggle 45 | { 46 | background-color: @light !important; 47 | border-color: @contrast !important; 48 | } 49 | 50 | .caret 51 | { 52 | border-top-color: @foreground; 53 | } 54 | 55 | .dropdown-menu 56 | { 57 | background: @light; 58 | border: 1px solid @contrast; 59 | } 60 | 61 | .menu-header 62 | { 63 | font-weight: bold; 64 | text-transform: uppercase; 65 | border-bottom: 1px solid @contrast; 66 | } 67 | 68 | .menu-divider 69 | { 70 | margin: 5px !important; 71 | border-bottom: 1px dashed @contrast; 72 | } 73 | 74 | .disabled 75 | { 76 | color: @foreground-disabled !important; 77 | cursor: default; 78 | border-color: @light2; 79 | } 80 | 81 | /* 82 | Menu-item icons 83 | */ 84 | 85 | .menu-item > a 86 | { 87 | color: @foreground; 88 | } 89 | 90 | .menu-item > a:before 91 | { 92 | display: inline-block; 93 | width: 30px; 94 | color: @foreground-less; 95 | text-align: center; 96 | font-family: FontAwesome; 97 | font-size: 10pt; 98 | content: ' '; 99 | } 100 | 101 | .menu-item > a.radio:before, .menu-item > a.check:before 102 | { 103 | color: transparent; 104 | content: '\f00c'; 105 | } 106 | 107 | .menu-item > a.checked:before 108 | { 109 | color: #000; 110 | } 111 | 112 | .menu-item > a.disabled:before 113 | { 114 | color: @light !important; 115 | } 116 | 117 | #action-search-pubchem:before { content: '\f1c0'; } 118 | #action-search-rcsb:before { content: '\f1c0'; } 119 | #action-search-cod:before { content: '\f1c0'; } 120 | 121 | #action-help:before { content: '\f1cd'; } 122 | #action-about:before { content: '\f05a'; } 123 | 124 | #action-share:before { content: '\f064'; } 125 | #action-embed:before { content: '\f121'; font-weight: bold; } 126 | #action-export-sketcher-png:before, #action-export-model-png:before, 127 | #action-export-model:before { content: '\f019'; } 128 | #action-data-infocard:before { content: '\f1ec'; } 129 | #action-data-spectra:before { content: '\f1fe'; } 130 | #model-source:before { content: '\f08e'; } 131 | #action-search-similarity:before { content: '\2248'; font-weight: bold; } 132 | #action-search-substructure:before { content: '\2282'; font-weight: bold; } 133 | #action-search-superstructure:before { content: '\2283'; font-weight: bold; } 134 | 135 | #action-model-reset:before { content: '\f021'; } 136 | #action-cif-unit-cell:before { content: '\f1b2'; } 137 | #action-cif-cubic-supercell:before { content: '\f1b3'; } 138 | #action-cif-flat-supercell:before { content: '\f1b3'; } 139 | -------------------------------------------------------------------------------- /src/svg/action/color.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 43 | 50 | 51 | 53 | 54 | 56 | image/svg+xml 57 | 59 | 60 | 61 | 62 | 63 | 68 | 78 | 88 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /src/less/search.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "vars"; 20 | 21 | #search-layer 22 | { 23 | margin: 0; 24 | text-align: center; 25 | background: @pubchem-pngbg; 26 | overflow: auto; 27 | } 28 | 29 | #search-layer > .container 30 | { 31 | font-size: 0; 32 | padding: 0 20px; 33 | } 34 | 35 | .load-more 36 | { 37 | cursor: pointer; 38 | margin: 10px; 39 | padding: 10px; 40 | font-size: 20pt; 41 | border: 1px solid @pubchem-pngbg; 42 | } 43 | 44 | .load-more:before 45 | { 46 | content: "Load more"; 47 | } 48 | 49 | .load-more-progress 50 | { 51 | cursor: default !important; 52 | background: @pubchem-pngbg !important; 53 | border-color: @pubchem-pngbg !important; 54 | box-shadow: none !important; 55 | } 56 | 57 | .load-more-progress:before 58 | { 59 | content: "Loading..."; 60 | } 61 | 62 | /* 63 | Search output: 64 |
65 |
Name 66 |
67 |
68 | */ 69 | 70 | .search-result 71 | { 72 | position: relative; 73 | display: inline-block; 74 | margin: 20px 0; 75 | width: 100%; 76 | vertical-align: top; 77 | 78 | font-size: medium; 79 | font-size: initial; 80 | text-decoration: none; 81 | color: @foreground; 82 | background: @light; 83 | 84 | border-radius: 5px; 85 | overflow: hidden; 86 | box-shadow: 0 3px 7px rgba(0, 0, 0, 0.4); 87 | } 88 | 89 | .search-result-pubchem 90 | { 91 | cursor: pointer; 92 | } 93 | 94 | .search-result-codid 95 | { 96 | line-height: 20px; 97 | color: @foreground-light; 98 | margin-bottom: 5px; 99 | } 100 | 101 | .search-result-title 102 | { 103 | cursor: pointer; 104 | display: block; 105 | height: 30px; 106 | line-height: 30px; 107 | padding: 10px 20px; 108 | 109 | text-align: center; 110 | text-decoration: none; 111 | text-overflow: ellipsis; 112 | 113 | color: @foreground; 114 | overflow: hidden; 115 | } 116 | 117 | .search-result-title > span 118 | { 119 | white-space: nowrap; 120 | text-decoration: none; 121 | } 122 | 123 | .search-result-description 124 | { 125 | padding: 20px; 126 | font-size: 11pt; 127 | 128 | word-wrap: break-word; 129 | text-align: left; 130 | 131 | overflow-x: hidden; 132 | overflow-y: auto; 133 | } 134 | 135 | .search-result-description > .expandable 136 | { 137 | margin: 0; 138 | } 139 | 140 | .search-result-description > .expandable > .expandable-title 141 | { 142 | border-width: 1px 0 1px 0; 143 | } 144 | 145 | .search-result-description > p 146 | { 147 | margin: 10px; 148 | } 149 | 150 | .search-result-description-cod 151 | { 152 | padding: 0; 153 | background: @light; 154 | } 155 | 156 | .search-result-img-wrap 157 | { 158 | font-size: 0; 159 | text-align: center; 160 | background-image: url(../img/misc/spinner.svg); 161 | background-repeat: no-repeat; 162 | background-position: center; 163 | } 164 | 165 | .search-result-img 166 | { 167 | display: inline-block; 168 | width: 300px; 169 | height: 300px; 170 | max-width: 100%; 171 | 172 | background-position: center; 173 | background-repeat: no-repeat; 174 | background-size: contain; 175 | 176 | } 177 | 178 | @media all and (min-width: 420px) 179 | { 180 | #search-layer 181 | { 182 | padding: 20px 20px 0 20px; 183 | } 184 | 185 | .search-result 186 | { 187 | width: 300px; 188 | margin: 20px; 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/svg/action/skeletal-off.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 40 | 43 | 44 | 46 | 47 | 49 | image/svg+xml 50 | 52 | 53 | 54 | 55 | 56 | Created with Raphaël 59 | 65 | 69 | 74 | 75 | 79 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/js/molpad/MPSelection.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | function MPSelection(mp) 20 | { 21 | this.cache = { atoms: [], bonds: [] }; 22 | this.mirrorSide = 1; 23 | this.startAngle = 0; 24 | this.currentAngle = 0; 25 | this.mp = mp; 26 | } 27 | 28 | MPSelection.prototype.hasCenter = function() 29 | { 30 | return typeof this.center === "object"; 31 | } 32 | 33 | /** 34 | * Updates the cached selection 35 | */ 36 | MPSelection.prototype.update = function() 37 | { 38 | this.cache.atoms = []; 39 | this.cache.bonds = []; 40 | 41 | for(var i = 0; i < this.mp.mol.atoms.length; i++) 42 | { 43 | if(this.mp.mol.atoms[i].isSelected()) 44 | { 45 | this.cache.atoms.push(i); 46 | } 47 | } 48 | for(var i = 0; i < this.mp.mol.bonds.length; i++) 49 | { 50 | if(this.mp.mol.bonds[i].isSelected()) 51 | { 52 | this.cache.bonds.push(i); 53 | } 54 | } 55 | } 56 | 57 | /** 58 | * Translate selection 59 | * Only atoms are translated 60 | * @param {Float} dx Horizontal translation 61 | * @param {Float} dy Vertical translation 62 | */ 63 | MPSelection.prototype.translate = function(dx, dy) 64 | { 65 | for(var i = 0; i < this.cache.atoms.length; i++) 66 | { 67 | this.mp.mol.atoms[this.cache.atoms[i]].translate(dx, dy); 68 | } 69 | } 70 | 71 | /** 72 | * Rotate selection using a mouse pointer 73 | * @param {MPPoint} pointer 74 | */ 75 | MPSelection.prototype.rotate = function(pointer) 76 | { 77 | this.currentAngle = this.mp.mol.rotateAtoms( 78 | this.center, pointer, this.cache.atoms, 79 | this.currentAngle, this.startAngle, 80 | this.mp.s.rotateSteps); 81 | } 82 | 83 | /** 84 | * Mirror selection using a pointer and a line 85 | * @param {Object} line 86 | * @param {MPPoint} pointer 87 | */ 88 | MPSelection.prototype.mirror = function(line, pointer) 89 | { 90 | var s = pointer.lineSide(line); 91 | 92 | if(s !== this.mirrorSide && s !== 0) 93 | { 94 | this.mirrorSide = s; 95 | 96 | for(var i = 0; i < this.cache.atoms.length; i++) 97 | { 98 | this.mp.mol.atoms[this.cache.atoms[i]].mirror(line, s); 99 | } 100 | } 101 | } 102 | 103 | /** 104 | * Clear current selection 105 | */ 106 | MPSelection.prototype.clear = function() 107 | { 108 | this.mp.mol.exec(function(obj) { 109 | obj.selected = false; 110 | }, true, true); 111 | this.center = undefined; 112 | this.update(); 113 | this.mp.requestRedraw(); 114 | } 115 | 116 | /** 117 | * Collapse current selection 118 | */ 119 | MPSelection.prototype.collapse = function() 120 | { 121 | this.mp.mol.collapseAtoms(this.cache.atoms.slice()); 122 | } 123 | 124 | 125 | /** 126 | * Remove current selection 127 | */ 128 | MPSelection.prototype.remove = function() 129 | { 130 | while(this.cache.atoms.length > 0) 131 | { 132 | this.mp.mol.removeAtom(this.cache.atoms[0]); 133 | } 134 | while(this.cache.bonds.length > 0) 135 | { 136 | this.mp.mol.removeBond(this.cache.bonds[0]); 137 | } 138 | } 139 | 140 | /** 141 | * Updates selection rotationCenter 142 | */ 143 | MPSelection.prototype.updateRotationCenter = function() 144 | { 145 | var v = []; 146 | for(var i = 0; i < this.cache.atoms.length; i++) 147 | { 148 | if(this.mp.mol.atoms[this.cache.atoms[i]].hasUnselectedNeighbors()) 149 | { 150 | v.push(this.cache.atoms[i]); 151 | } 152 | } 153 | 154 | if(v.length === 1 && this.cache.atoms.length > 1) 155 | { 156 | this.center = this.mp.mol.atoms[v[0]].center; 157 | this.centerAtom = v[0]; 158 | } 159 | else 160 | { 161 | this.center = undefined;//clear previous rotation center 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /src/js/molpad/MolPad.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | var MP_ZOOM_TO_COG = 0; 20 | var MP_ZOOM_TO_POINTER = 1; 21 | 22 | /** 23 | * Initialize MolPad in the given container 24 | * TODO: larger touch targets on high DPI screens 25 | * TODO: add implicit hydrogen as subset of MPAtom 26 | * TODO: collapse newly added implicit H atoms if !skeletal 27 | * TODO: always on feature for select tool 28 | * 29 | * @param {DOMElement} container 30 | * @param {Float} devicePixelRatio 31 | * @param {Object} buttons 32 | */ 33 | function MolPad(container, devicePixelRatio, buttons) 34 | { 35 | this.loadSettings(); 36 | 37 | //active tool data 38 | this.tool = { 39 | type: "bond",//bond || fragment || chain || charge || erase || drag || select || atom 40 | data: { type: MP_BOND_SINGLE }, 41 | selection: []//TMP 42 | }; 43 | 44 | this.mol = new MPMolecule(this); 45 | this.sel = new MPSelection(this); 46 | 47 | this.buttons = buttons; 48 | this.container = jQuery(container); 49 | this.offset = this.container.offset(); 50 | this.devicePixelRatio = devicePixelRatio || 1; 51 | 52 | this.setupEventHandling(); 53 | this.setupGraphics(); 54 | } 55 | 56 | /** 57 | * MolPad API 58 | */ 59 | 60 | MolPad.prototype.setTool = function(type, data) 61 | { 62 | this.tool.type = type; 63 | this.tool.data = data; 64 | } 65 | 66 | MolPad.prototype.onChange = function(cb) 67 | { 68 | this.changeCallback = cb; 69 | } 70 | 71 | MolPad.prototype.clear = function(cb) 72 | { 73 | this.mol.clear(); 74 | this.sel.update(); 75 | 76 | //retain old molecule translation in case of an undo 77 | this.scaleAbsolute(1 / this.matrix[0], this.width() / 2, this.height() / 2); 78 | 79 | this.redraw(true); 80 | this.mol.updateCopy(); 81 | } 82 | 83 | MolPad.prototype.changed = function() 84 | { 85 | jQuery(this.buttons.undo).toggleClass("tool-button-disabled", this.mol.stack.length === 0); 86 | jQuery(this.buttons.redo).toggleClass("tool-button-disabled", this.mol.reverseStack.length === 0); 87 | if(this.changeCallback !== undefined) this.changeCallback(); 88 | } 89 | 90 | MolPad.prototype.undo = function(noRedoPush) 91 | { 92 | this.dismissHandler(); 93 | if(this.mol.undo(noRedoPush)) this.changed(); 94 | } 95 | 96 | MolPad.prototype.redo = function() 97 | { 98 | this.dismissHandler(); 99 | if(this.mol.redo()) this.changed(); 100 | } 101 | 102 | MolPad.prototype.setSkeletalDisplay = function(on) 103 | { 104 | if(on === this.s.skeletalDisplay) return; 105 | 106 | this.dismissHandler(); 107 | this.s.skeletalDisplay = on; 108 | 109 | if(on) this.mol.removeImplicitHydrogen(); 110 | else this.mol.addImplicitHydrogen(); 111 | 112 | this.mol.invalidateAll(); 113 | 114 | this.clearRedrawRequest(); 115 | this.mol.updateCopy(); 116 | } 117 | 118 | MolPad.prototype.setColored = function(on) 119 | { 120 | this.s.atom.colored = this.s.bond.colored = on; 121 | this.s.fonts.isotope.fontStyle = this.s.fonts.element.fontStyle = 122 | this.s.fonts.charge.fontStyle = on ? "bold" : "normal"; 123 | this.redraw(true); 124 | } 125 | 126 | MolPad.prototype.toDataURL = function() 127 | { 128 | return this.canvas.toDataURL("image/png"); 129 | } 130 | 131 | /** 132 | * Load molfile 133 | * @param {String} mol 134 | * @param {Boolean} forceRemoveHydrogen 135 | */ 136 | MolPad.prototype.loadMOL = function(mol, forceRemoveHydrogen) 137 | { 138 | this.mol.loadMOL(mol); 139 | 140 | if(this.s.skeletalDisplay || forceRemoveHydrogen) 141 | { 142 | this.mol.removeImplicitHydrogen(); 143 | } 144 | 145 | this.center(); 146 | this.mol.updateCopy(); 147 | } 148 | 149 | MolPad.prototype.getMOL = function() 150 | { 151 | return this.mol.getMOL(); 152 | } 153 | 154 | MolPad.prototype.getSMILES = function() 155 | { 156 | return this.mol.getSMILES(); 157 | } 158 | -------------------------------------------------------------------------------- /src/js/Loader.Embed.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | /** 20 | * Lightweight Loader.js variant for /embed 21 | * @type {Object} 22 | */ 23 | var Loader = { 24 | PubChem: 25 | { 26 | loadCID: function(cid, name) 27 | { 28 | Progress.reset(3); 29 | 30 | name = name.charAt(0).toUpperCase() + name.slice(1); 31 | 32 | Messages.process(function() 33 | { 34 | //request 3D molecule 35 | Request.PubChem.sdf(cid, false, function(mol3d) 36 | { 37 | Model.loadMOL(mol3d); 38 | 39 | document.title = name || "MolView"; 40 | 41 | Progress.complete(); 42 | Messages.clear(); 43 | }, 44 | function()//error: resolve using NCI 45 | { 46 | Progress.increment(); 47 | 48 | Request.PubChem.properties(cid, "IsomericSMILES", function(data) 49 | { 50 | Progress.increment(); 51 | 52 | Request.CIR.resolve(data.PropertyTable.Properties[0].IsomericSMILES, false, 53 | function(mol3d) 54 | { 55 | Model.loadMOL(mol3d); 56 | 57 | document.title = name || "MolView"; 58 | 59 | Progress.complete(); 60 | Messages.clear(); 61 | }, 62 | function() 63 | { 64 | Messages.alert("load_fail"); 65 | }); 66 | }, 67 | function() 68 | { 69 | Messages.alert("load_fail"); 70 | }); 71 | }); 72 | }, "compound"); 73 | } 74 | }, 75 | 76 | RCSB: 77 | { 78 | loadPDBID: function(pdbid, name) 79 | { 80 | Progress.reset(2); 81 | 82 | function finish() 83 | { 84 | document.title = name || pdbid.toUpperCase(); 85 | 86 | Progress.complete(); 87 | Messages.clear(); 88 | } 89 | 90 | Messages.process(function() 91 | { 92 | Progress.increment(); 93 | 94 | Request.RCSB.PDB(pdbid, function(pdb) 95 | { 96 | if(!Detector.webgl) 97 | { 98 | if(MolView.mobile) 99 | { 100 | Messages.alert("mobile_old_no_macromolecules"); 101 | } 102 | else 103 | { 104 | if(Model.isJSmol()) 105 | { 106 | Model.loadPDB(pdb); 107 | finish(); 108 | } 109 | else//switch to JSmol 110 | { 111 | Model.preloadPDB(pdb); 112 | Model.setRenderEngine("JSmol", finish); 113 | } 114 | } 115 | } 116 | else 117 | { 118 | if(Model.isGLmol()) 119 | { 120 | Model.loadPDB(pdb); 121 | finish(); 122 | } 123 | else//switch to GLmol 124 | { 125 | Model.preloadPDB(pdb); 126 | Model.setRenderEngine("GLmol", finish); 127 | } 128 | } 129 | }, 130 | function() 131 | { 132 | Messages.alert("load_fail"); 133 | }); 134 | }, "macromolecule"); 135 | } 136 | }, 137 | 138 | COD: 139 | { 140 | loadCODID: function(codid, name) 141 | { 142 | Progress.reset(2); 143 | 144 | Messages.process(function() 145 | { 146 | Progress.increment(); 147 | 148 | Request.COD.CIF(codid, function(cif) 149 | { 150 | Model.loadCIF(cif); 151 | 152 | document.title = name || "COD: " + codid; 153 | 154 | Progress.complete(); 155 | Messages.clear(); 156 | }, 157 | function() 158 | { 159 | Messages.alert("load_fail"); 160 | }); 161 | }, "crystal"); 162 | } 163 | }, 164 | 165 | loadSMILES: function(smiles, title) 166 | { 167 | if(!Request.CIR.available) 168 | { 169 | Messages.alert("cir_down"); 170 | return; 171 | } 172 | 173 | Progress.reset(2); 174 | 175 | Request.resolve(smiles, 0, false, function(mol, cid) 176 | { 177 | Model.loadMOL(mol); 178 | Progress.complete(); 179 | Messages.clear(); 180 | document.title = title || "MolView"; 181 | }, 182 | function() 183 | { 184 | Messages.alert("load_fail"); 185 | }); 186 | } 187 | }; 188 | -------------------------------------------------------------------------------- /src/svg/action/clear.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 38 | 40 | 42 | 43 | 45 | image/svg+xml 46 | 48 | 49 | 50 | 51 | 52 | 54 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /src/js/chem/util/set.js: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2009-2010 GGA Software Services LLC 3 | * 4 | * This file may be distributed and/or modified under the terms of the 5 | * GNU Affero General Public License version 3 as published by the Free 6 | * Software Foundation and appearing in the file LICENSE.GPL included in 7 | * the packaging of this file. 8 | * 9 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 10 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 11 | ***************************************************************************/ 12 | 13 | if(!window.util) 14 | util = {}; 15 | 16 | util.Set = { 17 | empty: function () 18 | { 19 | return {}; 20 | }, 21 | 22 | single: function (item) 23 | { 24 | var set = {}; 25 | util.Set.add(set, item); 26 | return set; 27 | }, 28 | 29 | size: function (set) 30 | { 31 | var cnt = 0; 32 | for(var id in set) 33 | { 34 | if(set [id] !== Object.prototype[id]) 35 | { 36 | cnt++; 37 | } 38 | } 39 | return cnt; 40 | }, 41 | 42 | contains: function (set, v) 43 | { 44 | return typeof (set [v]) != "undefined" && set [v] !== Object.prototype[v]; 45 | }, 46 | 47 | subset: function (subset, superset) 48 | { 49 | for(var id in subset) 50 | { 51 | if(subset[id] !== Object.prototype[id]) 52 | { 53 | if(superset[id] !== subset[id]) 54 | { 55 | return false; 56 | } 57 | } 58 | } 59 | return true; 60 | }, 61 | 62 | intersection: function (set1, set2) 63 | { 64 | var set = {}; 65 | for(var id in set1) 66 | { 67 | if(set1[id] !== Object.prototype[id]) 68 | { 69 | if(set2[id] === set1[id]) 70 | { 71 | util.Set.add(set, id); 72 | } 73 | } 74 | } 75 | return set; 76 | }, 77 | 78 | disjoint: function (set1, set2) 79 | { 80 | for(var id in set1) 81 | { 82 | if(set1[id] !== Object.prototype[id]) 83 | { 84 | if(set2[id] === set1[id]) 85 | { 86 | return false; 87 | } 88 | } 89 | } 90 | return true; 91 | }, 92 | 93 | eq: function (set1, set2) 94 | { 95 | return util.Set.subset(set1, set2) && util.Set.subset(set2, set1); 96 | }, 97 | 98 | each: function (set, func, context) 99 | { 100 | for(var v in set) 101 | { 102 | if(set [v] !== Object.prototype[v]) 103 | { 104 | func.call(context, set [v]); 105 | } 106 | } 107 | }, 108 | 109 | filter: function (set, func, context) 110 | { 111 | var subset = {}; 112 | for(var v in set) 113 | { 114 | if(set [v] !== Object.prototype[v]) 115 | { 116 | if(func.call(context, set [v])) 117 | { 118 | subset[set [v]] = set [v]; 119 | } 120 | } 121 | } 122 | return subset; 123 | }, 124 | 125 | pick: function (set) 126 | { 127 | for(var v in set) 128 | { 129 | if(set [v] !== Object.prototype[v]) 130 | { 131 | return set [v]; 132 | } 133 | } 134 | return null; 135 | }, 136 | 137 | list: function (set) 138 | { 139 | var list = []; 140 | for(var v in set) 141 | { 142 | if(set [v] !== Object.prototype[v]) 143 | { 144 | list.push(set [v]); 145 | } 146 | } 147 | return list; 148 | }, 149 | 150 | add: function (set, item) 151 | { 152 | set [item] = item; 153 | }, 154 | 155 | mergeIn: function (set, other) 156 | { 157 | util.Set.each(other, function (item) 158 | { 159 | util.Set.add(set, item); 160 | }); 161 | }, 162 | 163 | remove: function (set, item) 164 | { 165 | var v = set [item]; 166 | delete set [item]; 167 | return v; 168 | }, 169 | 170 | clone: function (other) 171 | { 172 | var set = {}; 173 | util.Set.mergeIn(set, other); 174 | return set; 175 | }, 176 | 177 | fromList: function (list) 178 | { 179 | var set = {}; 180 | if(list) 181 | { 182 | for(var i = 0; i < list.length; ++i) 183 | { 184 | set [list[i] - 0] = list[i] - 0; 185 | } 186 | } 187 | return set; 188 | }, 189 | 190 | keySetInt: function (map) 191 | { 192 | var set = {}; 193 | map.each(function (id) 194 | { 195 | set [id - 0] = id - 0; 196 | }); 197 | return set; 198 | }, 199 | 200 | find: function (set, func, context) 201 | { 202 | for(var v in set) 203 | { 204 | if(set [v] !== Object.prototype[v]) 205 | { 206 | if(func.call(context, set [v])) 207 | { 208 | return v; 209 | } 210 | } 211 | } 212 | return null; 213 | } 214 | }; 215 | -------------------------------------------------------------------------------- /src/less/menu.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "vars"; 20 | @import (reference) "global"; 21 | 22 | #menu 23 | { 24 | display: block; 25 | position: absolute; 26 | margin: 0; 27 | padding: 0; 28 | height: @menubar-height + 1; 29 | 30 | overflow: hidden; 31 | overflow-x: auto; 32 | 33 | .no-select; 34 | } 35 | 36 | #menu-bar 37 | { 38 | position: absolute; 39 | top: 0; 40 | min-width: 100%; 41 | background: @menu-bar-bg; 42 | border-bottom: 1px solid @contrast; 43 | overflow: hidden; 44 | } 45 | 46 | .menu-open 47 | { 48 | height: 100% !important; 49 | } 50 | 51 | .menu-open > #menu-bar 52 | { 53 | overflow: visible; 54 | } 55 | 56 | #main-menu, #layout-menu, .dropdown, .menu-item, .menu-header, .menu-divider 57 | { 58 | margin: 0; 59 | padding: 0; 60 | list-style: none; 61 | } 62 | 63 | .dropdown 64 | { 65 | position: relative; 66 | margin: 0; 67 | padding: 0; 68 | } 69 | 70 | .dropdown-toggle 71 | { 72 | z-index: 1; 73 | position: relative; 74 | display: block; 75 | margin: 0; 76 | padding: 10px 15px; 77 | height: 20px; 78 | line-height: 20px; 79 | } 80 | 81 | .dropdown-menu 82 | { 83 | visibility: hidden; 84 | position: absolute; 85 | margin: -1px 0 0 0; 86 | padding: 5px 0; 87 | min-width: 200px; 88 | 89 | overflow-x: hidden; 90 | overflow-y: auto; 91 | } 92 | 93 | .dropdown-left 94 | { 95 | right: 0; 96 | } 97 | 98 | .dropdown-compact > .menu-item > a 99 | { 100 | padding: 5px 15px; 101 | } 102 | 103 | .dropdown-compact > .menu-item > a:before 104 | { 105 | display: none; 106 | } 107 | 108 | .menu-header 109 | { 110 | display: block; 111 | cursor: default; 112 | margin-top: 10px; 113 | margin-bottom: 5px; 114 | padding: 3px 10px; 115 | line-height: 15px; 116 | white-space: nowrap; 117 | } 118 | 119 | .menu-item > a 120 | { 121 | display: block; 122 | line-height: 20px; 123 | white-space: nowrap; 124 | } 125 | 126 | .dropdown.open 127 | { 128 | z-index: 2; 129 | } 130 | 131 | /* 132 | Only hide other dropdowns while displaying 133 | at least one other dropdown in order to: 134 | - prevent persistent hover style after all dropdowns are dismissed 135 | - hide scrollbar for hidden dropdown-menus 136 | */ 137 | .menu.open .dropdown:not(.open) > .dropdown-menu 138 | { 139 | display: none; 140 | } 141 | 142 | .dropdown.open > .dropdown-menu 143 | { 144 | visibility: visible; 145 | } 146 | 147 | /* search form */ 148 | #search 149 | { 150 | margin: 0 5px; 151 | background: @search-bar-bg; 152 | } 153 | 154 | 155 | #search > .input-wrapper > input, #search > .input-wrapper > button 156 | { 157 | background: @search-bar-bg; 158 | } 159 | 160 | #search-input 161 | { 162 | width: 300px; 163 | font-family: 'Open Sans', sans-serif; 164 | } 165 | 166 | #search-dropdown 167 | { 168 | display: inline-block; 169 | } 170 | 171 | #search-dropdown > .dropdown-toggle 172 | { 173 | border-color: transparent; 174 | } 175 | 176 | #search-dropdown > .dropdown-toggle:after 177 | { 178 | margin: 0; 179 | color: @foreground; 180 | content: '\f0d7'; 181 | } 182 | 183 | /* layout menu */ 184 | #layout-menu 185 | { 186 | font-size: 0; 187 | } 188 | 189 | #layout-menu > a 190 | { 191 | display: inline-block; 192 | margin: 0; 193 | padding: 0; 194 | width: 112px; 195 | height: 63px; 196 | 197 | opacity: 0.7; 198 | background-repeat: no-repeat; 199 | background-position: center; 200 | background-size: cover; 201 | } 202 | 203 | @media all and (min-width: 720px) 204 | { 205 | #layout-menu > a 206 | { 207 | width: 160px; 208 | height: 90px; 209 | } 210 | } 211 | 212 | #action-layout-model { background-image: url(../img/layout/model.svg); } 213 | #action-layout-sketcher { background-image: url(../img/layout/sketcher.svg); } 214 | #action-layout-vsplit { background-image: url(../img/layout/vsplit.svg); } 215 | #action-layout-hsplit { background-image: url(../img/layout/hsplit.svg); } 216 | -------------------------------------------------------------------------------- /src/js/molpad/MPFragments.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | /** 20 | * Input fragment data for MolPad 21 | * 1. you can pass this data as tool.data.frag 22 | * 2. all fragments use bondLength = 1 as default 23 | * 3. you have to multiply all coordinates with the real bondLength 24 | * 4. all fragments are centered on the positive side of the x-axis 25 | * 5. you can rotate the fragment coordinates around (0, 0) 26 | * 6. the first atom in each fragment.toAtom is the atom you have to connect to 27 | * when adding the fragment to an atom 28 | * 7. the first and the last atom in each fragment.toBond are the atoms 29 | * you have to merge with (first => from, last => to) 30 | */ 31 | var MPFragments = { 32 | benzene: {}, 33 | cyclopropane: {}, 34 | cyclobutane: {}, 35 | cyclopentane: {}, 36 | cyclohexane: {}, 37 | cycloheptane: {}, 38 | 39 | length: 1, 40 | lengthHydrogen: 34 / 55,//same as MolPad 41 | 42 | init: function() 43 | { 44 | //generate all fragments 45 | this.benzene = this.generateRing(6, true); 46 | this.cyclopropane = this.generateRing(3, false); 47 | this.cyclobutane = this.generateRing(4, false); 48 | this.cyclopentane = this.generateRing(5, false); 49 | this.cyclohexane = this.generateRing(6, false); 50 | this.cycloheptane = this.generateRing(7, false); 51 | }, 52 | 53 | generateRing: function(vertices, alternating) 54 | { 55 | var as = PI2 / vertices;//angle step 56 | var r = 0.5 / Math.sin(as / 2) * this.length; 57 | 58 | var ret = { 59 | full: this.createRing(vertices, alternating ? 2 : 0), 60 | toAtom: this.translate(this.createRing(vertices, alternating ? 2 : 0), r, 0),//move bond start to (0,0) 61 | toBond: this.rotate(this.translate(this.createRing(vertices, alternating ? 2 : 0), r, 0), 62 | { x: 0, y: 0 }, (Math.PI - as) / 2)//move bond start to (0,0), make first bond horizontal 63 | }; 64 | return ret; 65 | }, 66 | 67 | /** 68 | * Create ring data 69 | * @param {Integer} vertices Number of ring vertices 70 | * @param {Integer} alternating Double/single bond alternation: 71 | * 0 = none 72 | * 1 = first double on odd bonds 73 | * 2 = first double on even bonds 74 | */ 75 | createRing: function(vertices, alternating) 76 | { 77 | var frag = { atoms: [], bonds: [] }; 78 | var as = PI2 / vertices;//angle step 79 | frag.r = 0.5 / Math.sin(as / 2) * this.length; 80 | 81 | //ring 82 | for(var i = 0; i < vertices; i++) 83 | { 84 | //move a = 0 to left side to apply rule 4 85 | frag.atoms.push({ 86 | center: new MPPoint( 87 | frag.r * Math.cos(Math.PI + as * i),//start at the left side 88 | frag.r * Math.sin(Math.PI + as * i)), 89 | element: "C" 90 | }); 91 | frag.bonds.push({ 92 | from: i, 93 | to: i + 1 < vertices ? i + 1 : 0, 94 | type: alternating !== 0 ? (i % 2 === (2 - alternating) ? MP_BOND_SINGLE : MP_BOND_DOUBLE) : MP_BOND_SINGLE 95 | }); 96 | } 97 | 98 | return frag; 99 | }, 100 | 101 | clone: function(frag) 102 | { 103 | var copy = { atoms: [], bonds: [], r: frag.r }; 104 | 105 | for(var i = 0; i < frag.atoms.length; i++) 106 | { 107 | copy.atoms.push({ 108 | center: frag.atoms[i].center.clone(), 109 | element: frag.atoms[i].element 110 | }); 111 | } 112 | 113 | for(var i = 0; i < frag.bonds.length; i++) 114 | { 115 | copy.bonds.push({ 116 | from: frag.bonds[i].from, 117 | to: frag.bonds[i].to, 118 | type: frag.bonds[i].type 119 | }); 120 | } 121 | 122 | return copy; 123 | }, 124 | 125 | scale: function(frag, scale) 126 | { 127 | for(var i = 0; i < frag.atoms.length; i++) 128 | { 129 | frag.atoms[i].center.scale(scale); 130 | } 131 | return frag; 132 | }, 133 | 134 | rotate: function(frag, center, angle) 135 | { 136 | for(var i = 0; i < frag.atoms.length; i++) 137 | { 138 | frag.atoms[i].center.rotateAroundCenter(center, angle); 139 | } 140 | return frag; 141 | }, 142 | 143 | translate: function(frag, dx, dy) 144 | { 145 | for(var i = 0; i < frag.atoms.length; i++) 146 | { 147 | frag.atoms[i].center.translate(dx, dy); 148 | } 149 | return frag; 150 | } 151 | }; 152 | -------------------------------------------------------------------------------- /src/js/molpad/Utility.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | var PI2 = 2 * Math.PI; 20 | 21 | /** 22 | * Calculate if value is inside deviation relative to a number 23 | * @param {Float} val Input value 24 | * @param {Float} num Deviation base 25 | * @param {Float} dev Deviation value 26 | * @return {Boolean} 27 | */ 28 | function indev(val, num, dev) 29 | { 30 | return val > num - dev && val < num + dev; 31 | } 32 | 33 | /** 34 | * Calculate on which side b is relative to a in counter clockwise direction 35 | * @param {Float} a 36 | * @param {Float} b 37 | */ 38 | function radSide(a, b) 39 | { 40 | return angleBetween(a, b) < Math.PI ? 1 : -1; 41 | } 42 | 43 | /** 44 | * Normalize angle to value between 0 and 2PI 45 | * @param {Float} a 46 | */ 47 | function posRad(a) 48 | { 49 | while(a < 0) a += PI2; 50 | while(a > PI2) a -= PI2; 51 | return a; 52 | } 53 | 54 | /** 55 | * Calcualte smallest angle between two angles 56 | * @param {Float} a 57 | * @param {Float} b 58 | */ 59 | function smallestAngleBetween(a, b) 60 | { 61 | var d = Math.abs(posRad(a) - posRad(b)); 62 | return d < PI2 - d ? d : PI2 - d; 63 | } 64 | 65 | /** 66 | * Calculate angle between two angles where from is the first encountered angle 67 | * in counter clockwise direction 68 | * @param {Float} from 69 | * @param {Float} to 70 | */ 71 | function angleBetween(from, to) 72 | { 73 | from = posRad(from); 74 | to = posRad(to); 75 | 76 | if(to <= from)//the point 'to' on a circle is actually 2PI behind 77 | { 78 | return to - from + PI2; 79 | } 80 | else 81 | { 82 | return to - from; 83 | } 84 | } 85 | 86 | /** 87 | * Calculate the given clamped angle between a point and a center 88 | * @param {Float} start Angle offset 89 | * @param {MPPoint} center Center of rotation 90 | * @param {MPPoint} point Target point 91 | * @param {Float} steps Number of rotation steps in one circle 92 | * @return {Float} 93 | */ 94 | function clampedAngle(start, center, point, steps) 95 | { 96 | var a = center.angleTo(point); 97 | var clampFactor = steps / PI2; 98 | return posRad(Math.round((a - start) * clampFactor) / clampFactor 99 | + start);//clamp to x steps, normalize to startAngle 100 | } 101 | 102 | /** 103 | * Maps an array using a given map, removes all elements which are not 104 | * in the map 105 | * @param {Array} array 106 | * @param {Object} map 107 | * @return {Array} 108 | */ 109 | function mapArray(array, map) 110 | { 111 | for(var i = 0; i < array.length; i++) 112 | { 113 | if(map[array[i]] !== undefined) 114 | { 115 | array[i] = map[array[i]]; 116 | } 117 | else 118 | { 119 | array.splice(i, 1); 120 | i--; 121 | } 122 | } 123 | 124 | return array; 125 | } 126 | 127 | /** 128 | * Multiply all values in an array with a given multiplier into new array 129 | * @param {Array} array 130 | * @param {Float} mult 131 | * @return {Array} 132 | */ 133 | function transformArrayMult(array, mult) 134 | { 135 | var ret = [] 136 | for(var i = 0; i < array.length; i++) 137 | ret.push(array[i] * mult); 138 | return ret; 139 | } 140 | 141 | /** 142 | * Copy array into new array and add value 143 | * @param {Array} array 144 | * @param {Float} val 145 | * @return {Array} 146 | */ 147 | function transformArrayAdd(array, val) 148 | { 149 | var ret = [] 150 | for(var i = 0; i < array.length; i++) 151 | ret.push(array[i] + val); 152 | return ret; 153 | } 154 | 155 | /** 156 | * Also defined in main MolView Utility but this makes MolPad standalone 157 | * @param {String} nail 158 | * @param {Array} haystack 159 | */ 160 | function oneOf(nail, haystack) 161 | { 162 | return haystack.indexOf(nail) !== -1; 163 | } 164 | 165 | function getMultiTouchDelta(e) 166 | { 167 | var t = e.originalEvent.targetTouches; 168 | if(t.length <= 1) return 0; 169 | else 170 | { 171 | var dx = Math.abs(t[0].pageX - t[1].pageX); 172 | var dy = Math.abs(t[0].pageY - t[1].pageY); 173 | return Math.sqrt(dx * dx + dy * dy); 174 | } 175 | } 176 | 177 | function sign(x) 178 | { 179 | //polyfill from Mozilla 180 | x = +x;// convert to a number 181 | if(x === 0 || isNaN(x)) return x 182 | return x > 0 ? 1 : -1 183 | } 184 | -------------------------------------------------------------------------------- /src/datasets/JmolColors.js: -------------------------------------------------------------------------------- 1 | var JmolColors = { 2 | "hex": { 3 | "D": 0xFFFFC0, 4 | "H": 0xFFFFFF, 5 | "He": 0xD9FFFF, 6 | "Li": 0xCC80FF, 7 | "Be": 0xC2FF00, 8 | "B": 0xFFB5B5, 9 | "C": 0x909090, 10 | "N": 0x3050F8, 11 | "O": 0xFF0D0D, 12 | "F": 0x90E050, 13 | "Ne": 0xB3E3F5, 14 | "Na": 0xAB5CF2, 15 | "Mg": 0x8AFF00, 16 | "Al": 0xBFA6A6, 17 | "Si": 0xF0C8A0, 18 | "P": 0xFF8000, 19 | "S": 0xFFFF30, 20 | "Cl": 0x1FF01F, 21 | "Ar": 0x80D1E3, 22 | "K": 0x8F40D4, 23 | "Ca": 0x3DFF00, 24 | "Sc": 0xE6E6E6, 25 | "Ti": 0xBFC2C7, 26 | "V": 0xA6A6AB, 27 | "Cr": 0x8A99C7, 28 | "Mn": 0x9C7AC7, 29 | "Fe": 0xE06633, 30 | "Co": 0xF090A0, 31 | "Ni": 0x50D050, 32 | "Cu": 0xC88033, 33 | "Zn": 0x7D80B0, 34 | "Ga": 0xC28F8F, 35 | "Ge": 0x668F8F, 36 | "As": 0xBD80E3, 37 | "Se": 0xFFA100, 38 | "Br": 0xA62929, 39 | "Kr": 0x5CB8D1, 40 | "Rb": 0x702EB0, 41 | "Sr": 0x00FF00, 42 | "Y": 0x94FFFF, 43 | "Zr": 0x94E0E0, 44 | "Nb": 0x73C2C9, 45 | "Mo": 0x54B5B5, 46 | "Tc": 0x3B9E9E, 47 | "Ru": 0x248F8F, 48 | "Rh": 0x0A7D8C, 49 | "Pd": 0x006985, 50 | "Ag": 0xC0C0C0, 51 | "Cd": 0xFFD98F, 52 | "In": 0xA67573, 53 | "Sn": 0x668080, 54 | "Sb": 0x9E63B5, 55 | "Te": 0xD47A00, 56 | "I": 0x940094, 57 | "Xe": 0x429EB0, 58 | "Cs": 0x57178F, 59 | "Ba": 0x00C900, 60 | "La": 0x70D4FF, 61 | "Ce": 0xFFFFC7, 62 | "Pr": 0xD9FFC7, 63 | "Nd": 0xC7FFC7, 64 | "Pm": 0xA3FFC7, 65 | "Sm": 0x8FFFC7, 66 | "Eu": 0x61FFC7, 67 | "Gd": 0x45FFC7, 68 | "Tb": 0x30FFC7, 69 | "Dy": 0x1FFFC7, 70 | "Ho": 0x00FF9C, 71 | "Er": 0x00E675, 72 | "Tm": 0x00D452, 73 | "Yb": 0x00BF38, 74 | "Lu": 0x00AB24, 75 | "Hf": 0x4DC2FF, 76 | "Ta": 0x4DA6FF, 77 | "W": 0x2194D6, 78 | "Re": 0x267DAB, 79 | "Os": 0x266696, 80 | "Ir": 0x175487, 81 | "Pt": 0xD0D0E0, 82 | "Au": 0xFFD123, 83 | "Hg": 0xB8B8D0, 84 | "Tl": 0xA6544D, 85 | "Pb": 0x575961, 86 | "Bi": 0x9E4FB5, 87 | "Po": 0xAB5C00, 88 | "At": 0x754F45, 89 | "Rn": 0x428296, 90 | "Fr": 0x420066, 91 | "Ra": 0x007D00, 92 | "Ac": 0x70ABFA, 93 | "Th": 0x00BAFF, 94 | "Pa": 0x00A1FF, 95 | "U": 0x008FFF, 96 | "Np": 0x0080FF, 97 | "Pu": 0x006BFF, 98 | "Am": 0x545CF2, 99 | "Cm": 0x785CE3, 100 | "Bk": 0x8A4FE3, 101 | "Cf": 0xA136D4, 102 | "Es": 0xB31FD4, 103 | "Fm": 0xB31FBA, 104 | "Md": 0xB30DA6, 105 | "No": 0xBD0D87, 106 | "Lr": 0xC70066, 107 | "Rf": 0xCC0059, 108 | "Db": 0xD1004F, 109 | "Sg": 0xD90045, 110 | "Bh": 0xE00038, 111 | "Hs": 0xE6002E, 112 | "Mt": 0xEB0026 113 | }, 114 | "css": { 115 | "D": "#ffffc0", 116 | "H": "#000000", 117 | "He": "#849b9b", 118 | "Li": "#c87efa", 119 | "Be": "#82ab00", 120 | "B": "#c38a8a", 121 | "C": "#000000", 122 | "N": "#304ff7", 123 | "O": "#ff0d0d", 124 | "F": "#6dab3c", 125 | "Ne": "#7b9ca8", 126 | "Na": "#ab5cf2", 127 | "Mg": "#61b400", 128 | "Al": "#a79191", 129 | "Si": "#b09276", 130 | "P": "#ff8000", 131 | "S": "#c39517", 132 | "Cl": "#1dc51d", 133 | "Ar": "#63a2b0", 134 | "K": "#8f40d4", 135 | "Ca": "#2fc300", 136 | "Sc": "#969696", 137 | "Ti": "#94969a", 138 | "V": "#96969a", 139 | "Cr": "#8796c3", 140 | "Mn": "#9c7ac7", 141 | "Fe": "#e06633", 142 | "Co": "#db8293", 143 | "Ni": "#45b645", 144 | "Cu": "#c78033", 145 | "Zn": "#7d80b0", 146 | "Ga": "#bd8c8c", 147 | "Ge": "#668f8f", 148 | "As": "#bd80e3", 149 | "Se": "#e28f00", 150 | "Br": "#a62929", 151 | "Kr": "#53a6bc", 152 | "Rb": "#702eb0", 153 | "Sr": "#00d000", 154 | "Y": "#5fa4a4", 155 | "Zr": "#6ba2a2", 156 | "Nb": "#61a4a9", 157 | "Mo": "#4ea9a9", 158 | "Tc": "#3b9e9e", 159 | "Ru": "#248f8f", 160 | "Rh": "#0a7d8c", 161 | "Pd": "#006985", 162 | "Ag": "#969696", 163 | "Cd": "#ae9462", 164 | "In": "#a67573", 165 | "Sn": "#668080", 166 | "Sb": "#9e63b5", 167 | "Te": "#d47a00", 168 | "I": "#940094", 169 | "Xe": "#429eb0", 170 | "Cs": "#57178f", 171 | "Ba": "#00c900", 172 | "La": "#57a4c5", 173 | "Ce": "#989877", 174 | "Pr": "#869d7b", 175 | "Nd": "#7da07d", 176 | "Pm": "#69a581", 177 | "Sm": "#5ea883", 178 | "Eu": "#43b089", 179 | "Gd": "#31b48d", 180 | "Tb": "#23b890", 181 | "Dy": "#17bb92", 182 | "Ho": "#00c578", 183 | "Er": "#00c765", 184 | "Tm": "#00c94e", 185 | "Yb": "#00bf38", 186 | "Lu": "#00ab24", 187 | "Hf": "#42a8dc", 188 | "Ta": "#4ba2f9", 189 | "W": "#2194d6", 190 | "Re": "#267dab", 191 | "Os": "#266696", 192 | "Ir": "#175487", 193 | "Pt": "#9595a0", 194 | "Au": "#b9981a", 195 | "Hg": "#9595a9", 196 | "Tl": "#a6544d", 197 | "Pb": "#575961", 198 | "Bi": "#9e4fb5", 199 | "Po": "#ab5c00", 200 | "At": "#754f45", 201 | "Rn": "#428296", 202 | "Fr": "#420066", 203 | "Ra": "#007d00", 204 | "Ac": "#669ce4", 205 | "Th": "#00b8fc", 206 | "Pa": "#00a1ff", 207 | "U": "#008fff", 208 | "Np": "#0080ff", 209 | "Pu": "#006bff", 210 | "Am": "#545cf2", 211 | "Cm": "#785ce3", 212 | "Bk": "#8a4fe3", 213 | "Cf": "#a136d4", 214 | "Es": "#b31fd4", 215 | "Fm": "#B31FBA", 216 | "Md": "#B30DA6", 217 | "No": "#BD0D87", 218 | "Lr": "#C70066", 219 | "Rf": "#CC0059", 220 | "Db": "#D1004F", 221 | "Sg": "#D90045", 222 | "Bh": "#E00038", 223 | "Hs": "#E6002E", 224 | "Mt": "#EB0026", 225 | "Ds": "#9595a0", 226 | "Rg": "#b9981a", 227 | "Cn": "#9595a9" 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /src/less/form.less: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is part of MolView (http://molview.org) 3 | * Copyright (c) 2014, 2015 Herman Bergwerf 4 | * 5 | * MolView is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Affero General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * MolView is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Affero General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Affero General Public License 16 | * along with MolView. If not, see . 17 | */ 18 | 19 | @import (reference) "vars"; 20 | @import (reference) "global"; 21 | 22 | .form-box 23 | { 24 | margin-bottom: 1px;/* to fill :hover border-bottom-width */ 25 | 26 | color: @foreground; 27 | font-size: 12pt; 28 | font-family: 'Open Sans', sans-serif; 29 | text-decoration: none; 30 | background: transparent; 31 | border: 0; 32 | border-bottom: 2px solid @foreground-less; 33 | 34 | &:focus 35 | { 36 | outline: none; 37 | border-color: @highlight !important; 38 | } 39 | } 40 | 41 | .form-box-hover 42 | { 43 | margin-bottom: 0; 44 | border-width: 3px; 45 | border-color: @foreground-less; 46 | 47 | background: @light2; 48 | } 49 | 50 | .form-box-active 51 | { 52 | margin-bottom: 0; 53 | border-width: 3px; 54 | 55 | background: @highlight-light; 56 | border-color: @highlight !important; 57 | } 58 | 59 | /* input */ 60 | .input-wrapper 61 | { 62 | position: relative; 63 | height: 40px; 64 | font-size: 0 !important; 65 | white-space: nowrap; 66 | } 67 | 68 | .input-wrapper > input, .input-wrapper > button 69 | { 70 | display: inline-block; 71 | padding: 0; 72 | margin: 0; 73 | min-width: 40px; 74 | height: 40px; 75 | 76 | vertical-align: top; 77 | font-size: normal; 78 | font-size: initial; 79 | 80 | border: 0; 81 | } 82 | 83 | .input-wrapper > button:focus 84 | { 85 | outline: none; 86 | } 87 | 88 | .input-focus 89 | { 90 | display: block; 91 | position: absolute; 92 | top: 35px; 93 | right: 5px; 94 | left: 5px; 95 | height: 1px; 96 | 97 | background: @contrast; 98 | } 99 | 100 | input[type="text"] 101 | { 102 | cursor: text; 103 | margin: 0; 104 | 105 | -webkit-box-sizing: border-box; 106 | -moz-box-sizing: border-box; 107 | box-sizing: border-box; 108 | 109 | font-family: monospace; 110 | } 111 | 112 | input:focus 113 | { 114 | outline: none; 115 | } 116 | 117 | input[type="text"]:focus + .input-focus 118 | { 119 | background: @highlight !important; 120 | height: 2px; 121 | } 122 | 123 | input[type="text"].alert + .input-focus 124 | { 125 | background: @error !important; 126 | } 127 | 128 | .input 129 | { 130 | width: 100%; 131 | height: 30px; 132 | padding: 8px 10px 5px 10px; 133 | background: transparent; 134 | border: 0; 135 | border-bottom: 1px solid @foreground-light; 136 | } 137 | 138 | .input:focus 139 | { 140 | border-bottom: 2px solid @highlight !important; 141 | 142 | //border compensation trick 143 | height: 31px; 144 | margin-bottom: -1px; 145 | } 146 | 147 | /* select */ 148 | select 149 | { 150 | cursor: pointer; 151 | margin-top: 10px; 152 | margin-left: 10px; 153 | padding: 5px; 154 | max-width: 300px; 155 | 156 | color: @foreground; 157 | font-size: 12pt; 158 | font-family: 'Open Sans', sans-serif; 159 | text-decoration: none; 160 | } 161 | 162 | select:focus 163 | { 164 | outline: none; 165 | } 166 | 167 | option 168 | { 169 | background: @light; 170 | } 171 | 172 | /* checkbox */ 173 | input[type="checkbox"] 174 | { 175 | cursor: pointer; 176 | margin-bottom: 8px; 177 | vertical-align: middle; 178 | width: 18px; 179 | height: 18px; 180 | } 181 | 182 | /* button */ 183 | button, input[type="submit"] 184 | { 185 | cursor: pointer; 186 | display: inline-block; 187 | } 188 | 189 | .btn 190 | { 191 | .form-box; 192 | 193 | display: inline-block; 194 | margin-top: 10px; 195 | margin-left: 10px; 196 | padding: 5px 15px; 197 | } 198 | 199 | .btn-large 200 | { 201 | padding: 10px 20px; 202 | font-size: 18pt; 203 | } 204 | 205 | .close-btn 206 | { 207 | cursor: pointer; 208 | position: absolute; 209 | top: 0; 210 | right: 0; 211 | padding: 10px; 212 | 213 | line-height: 1; 214 | font-size: 32pt; 215 | color: #eee; 216 | } 217 | 218 | .close-btn:after 219 | { 220 | content: '\00D7'; 221 | } 222 | 223 | .btn-group 224 | { 225 | display: block; 226 | padding-bottom: 10px; 227 | } 228 | 229 | .btn-group-bar 230 | { 231 | display: block; 232 | padding-bottom: 10px; 233 | text-align: left; 234 | } 235 | 236 | /* table styling */ 237 | table 238 | { 239 | position: relative; 240 | color: #111; 241 | border-collapse: collapse; 242 | } 243 | 244 | td, th 245 | { 246 | padding: 5px 20px 5px 5px; 247 | min-width: 32px; 248 | border: 1px solid @contrast; 249 | } 250 | 251 | td 252 | { 253 | background-color: @light2; 254 | } 255 | 256 | tr:nth-child(even) > td 257 | { 258 | background-color: @light3; 259 | } 260 | 261 | th 262 | { 263 | background: @light; 264 | font-weight: bold; 265 | text-align: center; 266 | } 267 | 268 | td:first-child 269 | { 270 | font-weight: bold; 271 | } 272 | -------------------------------------------------------------------------------- /php/load.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | include_once("utility.php"); 21 | 22 | function load_metadata($q, $smiles, $cid, $pdbid, $codid) 23 | { 24 | global $root; 25 | 26 | //title 27 | $title = "MolView"; 28 | if(isset($q)) 29 | $title = ucfirst($q); 30 | else if(isset($pdbid)) 31 | $title = strtoupper($pdbid); 32 | else if(isset($codid)) 33 | $title = "COD: ".$codid; 34 | 35 | //description 36 | $description = "MolView is an intuitive, Open-Source web-application to make science and education more awesome!"; 37 | if(isset($q) || isset($smiles) || isset($cid)) 38 | $description = "View this molecule at http://molview.org"; 39 | else if(isset($pdbid)) 40 | $description = "View this macromolecule at http://molview.org"; 41 | 42 | //keywords 43 | $keywords = "molview,free,chemistry,app,molecules,proteins,crystals,spectroscopy"; 44 | if(isset($q)) $keywords .= ",".$q; 45 | 46 | //same as 47 | $same_as = ""; 48 | if(isset($q)) 49 | $same_as = "//en.wikipedia.org/wiki/".$q; 50 | else if(isset($cid)) 51 | $same_as = "https://pubchem.ncbi.nlm.nih.gov/summary/summary.cgi?cid=".$cid; 52 | else if(isset($pdbid)) 53 | $same_as = "//www.rcsb.org/pdb/explore/explore.do?structureId=".$pdbid; 54 | 55 | //image 56 | $image_url = $root."img/image.png"; 57 | $pubchem_query = null; 58 | $pubchem_value = null; 59 | if(isset($cid)) 60 | { $pubchem_query = "cid"; $pubchem_value = $cid; } 61 | else if(isset($smiles)) 62 | { $pubchem_query = "smiles"; $pubchem_value = $smiles; } 63 | else if(isset($q)) 64 | { $pubchem_query = "name"; $pubchem_value = $q; } 65 | else if(isset($pdbid)) 66 | $image_url = $root."api/image/pdb/".$pdbid.".jpg"; 67 | 68 | if(isset($pubchem_query))//data via PubChem 69 | { 70 | $json = http_get("https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/".$pubchem_query."/description/json?".$pubchem_query.'='.urlencode($pubchem_value)); 71 | $data = json_decode($json); 72 | 73 | if(isset($data -> InformationList -> Information)) 74 | { 75 | foreach($data -> InformationList -> Information as $record) 76 | { 77 | if(!isset($_title) && isset($record -> Title)) 78 | { 79 | $_title = ucfirst(humanize($record -> Title)); 80 | } 81 | if(!isset($_description) && isset($record -> Description)) 82 | { 83 | $_description = $record -> Description; 84 | } 85 | } 86 | 87 | if(isset($_title)) $title = $_title; 88 | if(isset($_description)) $description = $_description; 89 | } 90 | 91 | if(isset($data -> InformationList -> Information[0] -> CID) && $data -> InformationList -> Information[0] -> CID > 0) 92 | { 93 | if($pubchem_query != "cid")//redirect to ?cid 94 | { 95 | $query = preg_replace("/".($pubchem_query == "name" ? "q" : $pubchem_query). 96 | "=[^&]*/", "cid=".($data -> InformationList -> Information[0] -> CID), 97 | $_SERVER["QUERY_STRING"]);//remove old compound query 98 | header("Location: ?".$query, true, 302); 99 | } 100 | else 101 | { 102 | $same_as = "https://pubchem.ncbi.nlm.nih.gov/summary/summary.cgi?cid=". 103 | $data -> InformationList -> Information[0] -> CID; 104 | } 105 | } 106 | } 107 | else if(isset($pdbid))//data via RCSB 108 | { 109 | $xml = http_get("http://www.rcsb.org/pdb/rest/customReport?pdbids=".$pdbid."&customReportColumns=structureId,structureTitle"); 110 | $data = new SimpleXMLElement($xml); 111 | 112 | if(isset($data -> {"record"} -> {"dimStructure.structureId"})) 113 | { 114 | $title = $data -> {"record"} -> {"dimStructure.structureId"}; 115 | } 116 | if(isset($data -> {"record"} -> {"dimStructure.structureTitle"})) 117 | { 118 | $description = $data -> {"record"} -> {"dimStructure.structureTitle"}; 119 | } 120 | } 121 | else if(isset($codid))//data via COD 122 | { 123 | $cod = new mysqli("www.crystallography.net", "cod_reader", "", "cod"); 124 | if($cod -> connect_errno == 0) 125 | { 126 | $query = 'SELECT mineral,commonname,chemname,title FROM data WHERE file = '.$codid; 127 | if($result = $cod -> query($query)) 128 | { 129 | while($row = $result -> fetch_row())//print JSON 130 | { 131 | $title = isset($row[0]) ? $row[0] : (isset($row[1]) ? $row[1] : (isset($row[2]) ? $row[2] : $title)); 132 | $description = $row[3]; 133 | } 134 | } 135 | 136 | $cod -> close(); 137 | } 138 | } 139 | 140 | //refine PubChem image 141 | if(isset($pubchem_query)) 142 | { 143 | if($pubchem_query == "cid") 144 | { 145 | $image_url = $root."api/image/cid/".$pubchem_value.".png"; 146 | } 147 | } 148 | 149 | return array( 150 | "title" => htmlspecialchars($title), 151 | "description" => htmlspecialchars($description), 152 | "keywords" => htmlspecialchars($keywords), 153 | "same_as" => htmlspecialchars($same_as), 154 | "image_url" => htmlspecialchars($image_url), 155 | "pubchem_query" => htmlspecialchars($pubchem_query), 156 | "pubchem_value" => htmlspecialchars($pubchem_value) 157 | ); 158 | } 159 | -------------------------------------------------------------------------------- /src/js/chem/chem/dfs.js: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2009-2010 GGA Software Services LLC 3 | * 4 | * This file may be distributed and/or modified under the terms of the 5 | * GNU Affero General Public License version 3 as published by the Free 6 | * Software Foundation and appearing in the file LICENSE.GPL included in 7 | * the packaging of this file. 8 | * 9 | * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 10 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 11 | ***************************************************************************/ 12 | 13 | if(!window.chem || !chem.Struct) 14 | throw new Error("Molecule should be defined first"); 15 | 16 | chem.Dfs = function (mol, atom_data, components, nReactants) 17 | { 18 | this.molecule = mol; 19 | this.atom_data = atom_data; 20 | this.components = components; 21 | this.nComponentsInReactants = -1; 22 | this.nReactants = nReactants; 23 | 24 | this.vertices = new Array(this.molecule.atoms.count()); // Minimum size 25 | this.molecule.atoms.each(function (aid) 26 | { 27 | this.vertices[aid] = new chem.Dfs.VertexDesc(); 28 | }, this); 29 | 30 | this.edges = new Array(this.molecule.bonds.count()); // Minimum size 31 | this.molecule.bonds.each(function (bid) 32 | { 33 | this.edges[bid] = new chem.Dfs.EdgeDesc(); 34 | }, this); 35 | 36 | this.v_seq = new Array(); 37 | }; 38 | 39 | chem.Dfs.VertexDesc = function () 40 | { 41 | this.dfs_state = 0; // 0 -- not on stack 42 | // 1 -- on stack 43 | // 2 -- removed from stack 44 | this.parent_vertex = 0; // parent vertex in DFS tree 45 | this.parent_edge = 0; // edge to parent vertex 46 | this.branches = 0; // how many DFS branches go out from this vertex} 47 | }; 48 | 49 | chem.Dfs.EdgeDesc = function () 50 | { 51 | this.opening_cycles = 0; // how many cycles are 52 | // (i) starting with this edge 53 | // and (ii) ending in this edge's first vertex 54 | this.closing_cycle = 0; // 1 if this edge closes a cycle 55 | }; 56 | 57 | chem.Dfs.SeqElem = function (v_idx, par_vertex, par_edge) 58 | { 59 | this.idx = v_idx; // index of vertex in _graph 60 | this.parent_vertex = par_vertex; // parent vertex in DFS tree 61 | this.parent_edge = par_edge; // edge to parent vertex 62 | }; 63 | 64 | chem.Dfs.prototype.walk = function () 65 | { 66 | var v_stack = new Array(); 67 | var i, j; 68 | var cid = 0; 69 | var component = 0; 70 | 71 | while(true) 72 | { 73 | if(v_stack.length < 1) 74 | { 75 | var selected = -1; 76 | 77 | var findFunc = function (aid) 78 | { 79 | if(this.vertices[aid].dfs_state == 0) 80 | { 81 | selected = aid; 82 | return true; 83 | } 84 | return false; 85 | }; 86 | 87 | while(cid < this.components.length && selected == -1) 88 | { 89 | selected = util.Set.find(this.components[cid], findFunc, this); 90 | if(selected === null) 91 | { 92 | selected = -1; 93 | cid++; 94 | if(cid == this.nReactants) 95 | { 96 | this.nComponentsInReactants = component; 97 | } 98 | } 99 | } 100 | if(selected < -1) 101 | { 102 | this.molecule.atoms.find(findFunc, this); 103 | } 104 | if(selected == -1) 105 | break; 106 | this.vertices[selected].parent_vertex = -1; 107 | this.vertices[selected].parent_edge = -1; 108 | v_stack.push(selected); 109 | component++; 110 | } 111 | 112 | var v_idx = v_stack.pop(); 113 | var parent_vertex = this.vertices[v_idx].parent_vertex; 114 | 115 | var seq_elem = new chem.Dfs.SeqElem(v_idx, parent_vertex, this.vertices[v_idx].parent_edge); 116 | this.v_seq.push(seq_elem); 117 | 118 | this.vertices[v_idx].dfs_state = 2; 119 | 120 | var atom_d = this.atom_data[v_idx]; 121 | 122 | for(i = 0; i < atom_d.neighbours.length; i++) 123 | { 124 | var nei_idx = atom_d.neighbours[i].aid; 125 | var edge_idx = atom_d.neighbours[i].bid; 126 | 127 | if(nei_idx == parent_vertex) 128 | continue; 129 | 130 | if(this.vertices[nei_idx].dfs_state == 2) 131 | { 132 | this.edges[edge_idx].closing_cycle = 1; 133 | 134 | j = v_idx; 135 | 136 | while(j != -1) 137 | { 138 | if(this.vertices[j].parent_vertex == nei_idx) 139 | break; 140 | j = this.vertices[j].parent_vertex; 141 | } 142 | 143 | if(j == -1) 144 | throw new Error("Cycle unwind error"); 145 | 146 | this.edges[this.vertices[j].parent_edge].opening_cycles++; 147 | this.vertices[v_idx].branches++; 148 | 149 | seq_elem = new chem.Dfs.SeqElem(nei_idx, v_idx, edge_idx); 150 | this.v_seq.push(seq_elem); 151 | } 152 | else 153 | { 154 | if(this.vertices[nei_idx].dfs_state == 1) 155 | { 156 | j = v_stack.indexOf(nei_idx); 157 | 158 | if(j == -1) 159 | throw new Error("Internal: removing vertex from stack"); 160 | 161 | v_stack.splice(j, 1); 162 | 163 | var parent = this.vertices[nei_idx].parent_vertex; 164 | 165 | if(parent >= 0) 166 | this.vertices[parent].branches--; 167 | } 168 | 169 | this.vertices[v_idx].branches++; 170 | this.vertices[nei_idx].parent_vertex = v_idx; 171 | this.vertices[nei_idx].parent_edge = edge_idx; 172 | this.vertices[nei_idx].dfs_state = 1; 173 | v_stack.push(nei_idx); 174 | } 175 | } 176 | } 177 | }; 178 | 179 | chem.Dfs.prototype.edgeClosingCycle = function (e_idx) 180 | { 181 | return this.edges[e_idx].closing_cycle != 0; 182 | }; 183 | 184 | chem.Dfs.prototype.numBranches = function (v_idx) 185 | { 186 | return this.vertices[v_idx].branches; 187 | }; 188 | 189 | chem.Dfs.prototype.numOpeningCycles = function (e_idx) 190 | { 191 | return this.edges[e_idx].opening_cycles; 192 | }; 193 | 194 | chem.Dfs.prototype.toString = function () 195 | { 196 | var str = ''; 197 | this.v_seq.each(function (seq_elem) 198 | { 199 | str += seq_elem.idx + ' -> ' 200 | }); 201 | str += '*'; 202 | return str; 203 | }; 204 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | License 2 | ======= 3 | ``` 4 | MolView (http://molview.org) 5 | Copyright (c) 2014, 2015 Herman Bergwerf 6 | 7 | MolView is free software: you can redistribute it and/or modify 8 | it under the terms of the GNU Affero General Public License as published by 9 | the Free Software Foundation, either version 3 of the License, or 10 | (at your option) any later version. 11 | 12 | MolView is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU Affero General Public License for more details. 16 | 17 | You should have received a copy of the GNU Affero General Public License 18 | along with MolView. If not, see . 19 | ``` 20 | 21 | Third-party licenses 22 | ==================== 23 | Below is a list of all third-party libraries used in MolView. 24 | If you believe your code is used in MolView and should be contained in this list, 25 | please contact me via 26 | Included third-party code is **not** subject to the MolView license (AGPL) 27 | All modifications to third-party code are subject to its respective 28 | license or agreement. 29 | 30 | --- 31 | 32 | ## ChemDoodleWeb 33 | ``` 34 | ChemDoodle Web Components 6.0.1 35 | 36 | http://web.chemdoodle.com 37 | 38 | Copyright 2009-2014 iChemLabs, LLC. All rights reserved. 39 | 40 | The ChemDoodle Web Components library is licensed under version 3 41 | of the GNU GENERAL PUBLIC LICENSE. 42 | 43 | You may redistribute it and/or modify it under the terms of the 44 | GNU General Public License as published by the Free Software Foundation, 45 | either version 3 of the License, or (at your option) any later version. 46 | 47 | As an exception to the GPL, you may distribute this packed form of 48 | the code without the copy of the GPL license normally required, 49 | provided you include this license notice and a URL through which 50 | recipients can access the corresponding unpacked source code. 51 | 52 | This program is distributed in the hope that it will be useful, 53 | but WITHOUT ANY WARRANTY; without even the implied warranty of 54 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 55 | GNU General Public License for more details. 56 | 57 | Please contact iChemLabs for 58 | alternate licensing options. 59 | ``` 60 | See: http://web.chemdoodle.com/ 61 | 62 | --- 63 | 64 | ## FileSaver.js and Blob.js 65 | ``` 66 | Copyright (c) 2014 [Eli Grey](http://eligrey.com) 67 | MIT License 68 | ``` 69 | See: https://github.com/eligrey/FileSaver.js 70 | and https://github.com/eligrey/Blob.js 71 | 72 | --- 73 | 74 | ## GLmol 75 | ``` 76 | GLmol - Molecular Viewer on WebGL/Javascript (0.47) 77 | (C) Copyright 2011-2012, biochem_fan 78 | License: dual license of MIT or LGPL3 79 | ``` 80 | See: https://github.com/biochem-fan/GLmol 81 | 82 | --- 83 | 84 | ## iView 85 | ``` 86 | Copyright (c) 2012-2014 Chinese University of Hong Kong 87 | License: Apache License 2.0 88 | Hongjian Li, Kwong-Sak Leung, Takanori Nakane and Man-Hon Wong. 89 | iview: an interactive WebGL visualizer for protein-ligand complex. 90 | BMC Bioinformatics, 15(1):56, 2014. 91 | ``` 92 | See: https://github.com/HongjianLi/istar/tree/master/public/iview 93 | 94 | --- 95 | 96 | ## JSmol 97 | ``` 98 | Jmol is offered under the LGPL License (GNU Lesser General Public License) 99 | ``` 100 | See: http://wiki.jmol.org/index.php/License 101 | 102 | --- 103 | 104 | ## jQuery 105 | ``` 106 | jQuery JavaScript Library v2.1.0 107 | http://jquery.com/ 108 | 109 | Includes Sizzle.js 110 | http://sizzlejs.com/ 111 | 112 | Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors 113 | Released under the MIT license 114 | http://jquery.org/license 115 | 116 | Date: 2014-01-23T21:10Z 117 | ``` 118 | See: http://jquery.com/ 119 | 120 | --- 121 | 122 | ## jQuery Hotkeys 123 | ``` 124 | MIT or GPL Version 2 125 | ``` 126 | See: https://github.com/jeresig/jquery.hotkeys 127 | 128 | --- 129 | 130 | ## Ketcher 131 | ``` 132 | Ketcher is Copyright (C) of GGA Software Services LLC 2009-2010. 133 | 134 | This program is free software: you can redistribute it and/or modify 135 | it under the terms of the GNU Affero General Public License as published 136 | by the Free Software Foundation, version 3 of the License. 137 | 138 | This program is distributed in the hope that it will be useful, 139 | but WITHOUT ANY WARRANTY; without even the implied warranty of 140 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141 | GNU Affero General Public License for more details. 142 | 143 | You should have received a copy of the GNU Affero General Public License 144 | along with this program. If not, see 145 | ``` 146 | See: https://github.com/ggasoftware/ketcher 147 | 148 | --- 149 | 150 | ## MobileDetect 151 | ``` 152 | Code and contributions have 'MIT License' 153 | More details: https://github.com/serbanghita/Mobile-Detect/blob/master/LICENSE.txt 154 | ``` 155 | See: https://github.com/serbanghita/Mobile-Detect/ 156 | 157 | --- 158 | 159 | ## Parsedown 160 | ``` 161 | The MIT License (MIT) 162 | Copyright (c) 2013 Emanuil Rusev, erusev.com 163 | ``` 164 | See: https://github.com/erusev/parsedown 165 | 166 | --- 167 | 168 | ## PeriodicTable 169 | See: https://github.com/diniska/chemistry/blob/master/PeriodicalTable/periodicTable.json 170 | 171 | --- 172 | 173 | ## Three.js 174 | ``` 175 | The MIT License 176 | Copyright (c) 2010-2014 three.js authors 177 | ``` 178 | See: https://github.com/mrdoob/three.js 179 | 180 | --- 181 | 182 | Full licenses 183 | ============= 184 | - **MIT**: see [licenses/mit.txt](licenses/mit.txt) 185 | - **GPL2**: see [licenses/gpl.txt](licenses/gpl-2.0.txt) 186 | - **GPL3**: see [licenses/gpl.txt](licenses/gpl.txt) 187 | - **AGPL3**: see [licenses/agpl.txt](licenses/agpl.txt) 188 | - **LGPL3**: see [licenses/lgpl.txt](licenses/lgpl.txt) 189 | - **Apache License 2.0**: see [licenses/apache-license-2.0.txt](licenses/apache-license-2.0.txt) 190 | -------------------------------------------------------------------------------- /php/nist.php: -------------------------------------------------------------------------------- 1 | . 18 | */ 19 | 20 | /* 21 | PHP script for processing and retrieving data from the NIST Chemistry Webbook 22 | 23 | Available spectra on NIST Chemistry WebBook: 24 | - Mass spectrum 25 | - IR spectrum 26 | - UV-Visible spectrum 27 | 28 | Notes: 29 | - Index = 0 for Mass spectrum 30 | - Index = 0 - 2 for IR spectrum 31 | - Index = 0 for UV-Visible spectrum 32 | 33 | @param type Query type: lookup, mass, ir, uvvis 34 | @param cas CAS Registry Number 35 | @param i IR spectrum index 36 | @return JSON data 37 | */ 38 | 39 | include_once("utility.php"); 40 | 41 | error_reporting(0); 42 | parse_str($_SERVER["QUERY_STRING"]); 43 | 44 | if(!isset($type) || !isset($cas)) 45 | { 46 | http_response_code(400); 47 | exit("Bad request"); 48 | } 49 | 50 | if($type == "lookup") 51 | { 52 | header("Content-Type: application/json"); 53 | 54 | /* 55 | Extract spectra from Coblentz and NIST Mass Spec Data Center 56 | 57 | Returns (example for cas=50-78-2): 58 | { 59 | "mass": true, 60 | "uvvis": true, 61 | "ir": [ 62 | { 63 | "i": 0, 64 | "state": "Not specified, most likely a prism, grating, or hybrid spectrometer.", 65 | "source": "(NO SPECTRUM, ONLY SCANNED IMAGE IS AVAILABLE)" 66 | }, 67 | { 68 | "i": 1, 69 | "state": "SOLID (KBr DISC) VS KBr", 70 | "source": "PERKIN-ELMER 21 (GRATING); DIGITIZED BY COBLENTZ SOCIETY (BATCH I) FROM HARD COPY; 2 cm" 71 | } 72 | ] 73 | } 74 | */ 75 | 76 | $nist_page = http_get("https://webbook.nist.gov/cgi/cbook.cgi?Mask=80&ID=".$cas); 77 | 78 | echo "{"; 79 | echo '"url":'.json_encode(utf8_encode("https://webbook.nist.gov/cgi/cbook.cgi?ID=".$cas)); 80 | echo ',"mass":'.(strrpos($nist_page, "Mass spectrum (electron ionization)") === false ? "false" : "true"); 81 | echo ',"uvvis":'.(strrpos($nist_page, "UV/Visible spectrum") === false ? "false" : "true"); 82 | echo ',"ir":['; 83 | 84 | //if there is only one records (Index=0) the result is directly embeded into the webpage (see caffeine) 85 | // State<\/th>([^<]*)<\/td><\/tr> 86 | preg_match_all('/State<\/th>([^<]*)<\/td><\/tr>/', $nist_page, $records); 87 | 88 | if(count($records[0]) > 0) 89 | { 90 | preg_match_all('/Index=([0-9])/', $nist_page, $indexes); 91 | echo '{"i":'.$indexes[1][0].',"state":'.json_encode(utf8_encode($records[1][0])).',"source":""}'; 92 | } 93 | else//second method 94 | { 95 | $nist_page = explode("\n", $nist_page); 96 | $inlist = false; 97 | $listnr = 0; 98 | $length = 0; 99 | 100 | $key = array_search('

IR Spectrum

', $nist_page); 101 | if($key !== false) 102 | { 103 | $idx = $key + 1;//skip "Go to ..." line 104 | } 105 | else 106 | { 107 | echo "]}"; 108 | return; 109 | } 110 | 111 | //loop trough NIST webpage lines 112 | for($idx = 0; $idx < count($nist_page); $idx++) 113 | { 114 | if($inlist == false)//we are not in an IR spectrum list 115 | { 116 | $pos1 = strpos($nist_page[$idx], '

Data compiled by: Coblentz Society, Inc.

'); 117 | $pos2 = strpos($nist_page[$idx], '

Data compiled by: NIST Mass Spec Data Center, S.E. Stein, director

'); 118 | if($pos1 !== false || $pos2 !== false)//we are in an IR spectrum list 119 | { 120 | $inlist = true; 121 | $listnr++; 122 | $idx++;//skip "
    " 123 | } 124 | } 125 | else 126 | { 127 | $pos = strpos($nist_page[$idx], 'Index='); 128 | if($pos !== false)//format the data of this IR spectrum 129 | { 130 | preg_match_all('/[i"]>([A-z][^;<]*)(?:[^<\/]{2}|)([^<]*)/', $nist_page[$idx], $results); 131 | if(count($results[0]) > 0) 132 | { 133 | preg_match_all('/Index=([0-9])/', $nist_page[$idx], $indexes); 134 | 135 | if($length > 0) echo ","; 136 | echo "{"; 137 | echo '"i":'.json_encode(utf8_encode($indexes[1][count($indexes[1]) - 1])).",";//pick last Index=n in this line 138 | echo '"state":'.json_encode(utf8_encode($results[1][0])).","; 139 | echo '"source":'.json_encode(utf8_encode($results[2][0])); 140 | echo "}"; 141 | 142 | $length++; 143 | } 144 | } 145 | else//this might be the end of this IR spectrum list 146 | { 147 | $pos = strpos($nist_page[$idx], '
'); 148 | if($pos !== false) 149 | { 150 | $inlist = false; 151 | if($listnr >= 2) break; 152 | } 153 | } 154 | } 155 | } 156 | } 157 | 158 | echo "]}"; 159 | } 160 | else if($type == "mass") 161 | { 162 | header("Content-Type: text"); 163 | echo_curl("https://webbook.nist.gov/cgi/cbook.cgi?JCAMP=".$cas."&Type=Mass&Index=0"); 164 | } 165 | else if($type == "ir") 166 | { 167 | header("Content-Type: text"); 168 | if(!isset($i)) $i = 0; 169 | echo_curl("https://webbook.nist.gov/cgi/cbook.cgi?JCAMP=".$cas."&Type=IR&Index=".$i); 170 | } 171 | else if($type == "uvvis") 172 | { 173 | header("Content-Type: text"); 174 | echo_curl("https://webbook.nist.gov/cgi/cbook.cgi?JCAMP=".$cas."&Type=UVVis&Index=0"); 175 | } 176 | --------------------------------------------------------------------------------