├── docs ├── tags.png ├── text.png ├── preview.png ├── changelog.md └── install.md ├── kirby-keyword-map.php ├── package.json ├── fields └── keywordmap │ ├── template.php │ ├── assets │ ├── js │ │ ├── src │ │ │ ├── color-hash │ │ │ │ ├── license.txt │ │ │ │ └── color-hash.js │ │ │ ├── mark.js │ │ │ │ ├── license.txt │ │ │ │ └── jquery.mark.js │ │ │ └── script.js │ │ └── dist │ │ │ └── script.min.js │ ├── css │ │ ├── style.min.css │ │ └── style.css │ └── scss │ │ └── style.scss │ └── keywordmap.php ├── gulpfile.js └── readme.md /docs/tags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirby-deprecated-plugins/kirby-keyword-map/HEAD/docs/tags.png -------------------------------------------------------------------------------- /docs/text.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirby-deprecated-plugins/kirby-keyword-map/HEAD/docs/text.png -------------------------------------------------------------------------------- /docs/preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kirby-deprecated-plugins/kirby-keyword-map/HEAD/docs/preview.png -------------------------------------------------------------------------------- /kirby-keyword-map.php: -------------------------------------------------------------------------------- 1 | set('field', 'keywordmap', __DIR__ . DS . 'fields' . DS . 'keywordmap'); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kirby-keyword-map", 3 | "description": "SEO keyword map for Kirby CMS panel", 4 | "author": "Jens Törnell ", 5 | "version": "0.5", 6 | "type": "kirby-plugin", 7 | "license": "MIT" 8 | } -------------------------------------------------------------------------------- /fields/keywordmap/template.php: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 | 7 |
8 |
9 |
-------------------------------------------------------------------------------- /docs/changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | **0.5** 4 | 5 | - Updated limiters with `!?()[]` characters which means that it will match the keywords better. 6 | - Changed cursor to `not-allowed` to make the preview look a bit less editable. 7 | - Possible to toggle the preview on/off. Good for long texts. 8 | - Toggle mode is saved to local storage to be remembered in the next refresh. 9 | 10 | **0.4** 11 | 12 | - The keywords now have different colors, based on [color-hash](https://github.com/zenozeng/color-hash). 13 | - When only 1 match is found, it does not show the counter, just highlight with a color. 2 or more matches gives a counter. 14 | - Major javascript rewrites. 15 | 16 | **0.3** 17 | 18 | - Added word counters. 19 | - Minor css fixes. 20 | 21 | **0.2** 22 | 23 | - Fixed major bug that made the field not work with a single language installation. 24 | - Remove value in console.log. 25 | - Color a keyword tab if it's in the text. 26 | 27 | **0.1** 28 | 29 | - Initial release -------------------------------------------------------------------------------- /docs/install.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | Use one of the alternatives below. 4 | 5 | ## 1. Kirby CLI 6 | 7 | If you are using the [Kirby CLI](https://github.com/getkirby/cli) you can install this plugin by running the following commands in your shell: 8 | 9 | ``` 10 | $ cd path/to/kirby 11 | $ kirby plugin:install jenstornell/kirby-keyword-map 12 | ``` 13 | 14 | ## 2. Clone or download 15 | 16 | 1. [Clone](https://github.com/jenstornell/kirby-keyword-map.git) or [download](https://github.com/jenstornell/kirby-keyword-map/archive/master.zip) this repository. 17 | 2. Unzip the archive if needed and rename the folder to `kirby-keyword-map`. 18 | 19 | **Make sure that the plugin folder structure looks like this:** 20 | 21 | ``` 22 | site/plugins/kirby-keyword-map/ 23 | ``` 24 | 25 | ## 3. Git Submodule 26 | 27 | If you know your way around Git, you can download this plugin as a submodule: 28 | 29 | ``` 30 | $ cd path/to/kirby 31 | $ git submodule add https://github.com/jenstornell/kirby-keyword-map site/plugins/kirby-keyword-map 32 | ``` -------------------------------------------------------------------------------- /fields/keywordmap/assets/js/src/color-hash/license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Zeno Zeng 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /fields/keywordmap/assets/js/src/mark.js/license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014–2017 Julian Motz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | var gulp = require('gulp'); 2 | var sass = require('gulp-sass'); 3 | var autoprefixer = require('gulp-autoprefixer'); 4 | var cssmin = require('gulp-cssmin'); 5 | var concat = require('gulp-concat'); 6 | var uglify = require('gulp-uglify'); 7 | var notify = require('gulp-notify'); 8 | var rename = require('gulp-rename'); 9 | 10 | gulp.task('field_css', function() { 11 | return gulp.src(['fields/keywordmap/assets/scss/style.scss']) 12 | .pipe(sass()) 13 | .pipe(autoprefixer()) 14 | .pipe(gulp.dest('fields/keywordmap/assets/css')) 15 | .pipe(rename({suffix: '.min'})) 16 | .pipe(cssmin()) 17 | .pipe(gulp.dest('fields/keywordmap/assets/css')) 18 | .pipe(notify("CSS generated!")) 19 | ; 20 | }); 21 | 22 | // JS 23 | gulp.task('field_js', function() { 24 | gulp.src('fields/keywordmap/assets/js/src/**/*.js') 25 | .pipe(concat('script.js')) 26 | .pipe(uglify()) 27 | .pipe(rename({suffix: '.min'})) 28 | .pipe(gulp.dest('fields/keywordmap/assets/js/dist')) 29 | .pipe(notify("JS generated!")) 30 | ; 31 | }); 32 | 33 | // Default 34 | gulp.task('default',function() { 35 | gulp.watch('fields/keywordmap/assets/scss/**/*.scss',['field_css']); 36 | gulp.watch('fields/keywordmap/assets/js/src/**/*.js',['field_js']); 37 | }); -------------------------------------------------------------------------------- /fields/keywordmap/keywordmap.php: -------------------------------------------------------------------------------- 1 | array( 6 | 'dist/script.min.js', 7 | ), 8 | 'css' => array( 9 | 'style.min.css', 10 | ) 11 | ); 12 | 13 | public function __construct() { 14 | $this->separator = ','; 15 | $this->lower = true; 16 | } 17 | 18 | public function input() { 19 | if(site()->language()) { 20 | $lang = site()->language()->code(); 21 | $content = $this->page->content($lang)->get($this->name())->value(); 22 | } else { 23 | $content = $this->page->content()->get($this->name())->value(); 24 | } 25 | 26 | $input = parent::input(); 27 | $input->attr['value'] = (!empty($content)) ? $input->attr['value'] : ''; 28 | $input->addClass('keywordmap-tags'); 29 | 30 | $html = tpl::load( __DIR__ . DS . 'template.php', $data = array( 31 | 'field' => $this, 32 | 'page' => $this->page() 33 | )); 34 | return $input . $html; 35 | } 36 | 37 | public function element() { 38 | $element = parent::element(); 39 | $element->data('field', self::$fieldname); 40 | if(isset($this->target)) { 41 | $element->data('target', $this->target); 42 | } 43 | return $element; 44 | } 45 | } -------------------------------------------------------------------------------- /fields/keywordmap/assets/css/style.min.css: -------------------------------------------------------------------------------- 1 | .kwm-disabled .kwm-toggle,.kwm-toggle{border-bottom:2px solid #ddd}.keywordmap{padding:.5em;background:#fff;border:2px solid #ddd;border-top:none;line-height:24px;cursor:not-allowed}.keywordmap mark{color:#fff;display:inline-block;padding:0 4px;border-radius:3px;line-height:20px;margin:2px}.keywordmap mark mark{margin:4px 0}.kwm-toggle{border-left:2px solid #ddd;border-right:2px solid #ddd;text-align:center;padding:.5em;background:#eee;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border-top:2px solid #ddd}.kwm-show{display:none}.kwm-disabled .kwm-show,.kwm-hide{display:block}.kwm-disabled .keywordmap,.kwm-disabled .kwm-hide{display:none}.kwt-count{background:rgba(0,0,0,.2);padding:0 .25em;border-radius:3px;font-size:.8em;margin-left:.5em}.keywordmap-tags{border-bottom:2px solid #efefef;border-bottom:none}.keywordmap-tags.input-is-focused{border:2px solid #8dae28!important}.keywordmap-tags.input-is-focused .tag,.keywordmap-tags.input-is-focused .tag-label:focus{background:#eee}.keywordmap-tags.input-is-focused .tag.active,.keywordmap-tags.input-is-focused .tag.active .tag-label:focus{background:#8dae28}.keywordmap-tags .tag{background:#eee}.keywordmap-tags .tag.active .tag-label{color:#fff}.keywordmap-tags .tag.active .tag-x{color:rgba(255,255,255,.75)}.keywordmap-tags .tag.active .tag-x:hover{color:#fff}.keywordmap-tags .tag .tag-label{background:#eee;color:#000}.keywordmap-tags .tag .tag-x{color:#777;border-left:1px solid #fff!important}.keywordmap-tags .tag .tag-x:hover{color:#000} -------------------------------------------------------------------------------- /fields/keywordmap/assets/scss/style.scss: -------------------------------------------------------------------------------- 1 | .keywordmap { 2 | padding: .5em; 3 | background: #fff; 4 | border: 2px solid #ddd; 5 | border-top: none; 6 | line-height: 24px; 7 | cursor: not-allowed; 8 | mark { 9 | color: #fff; 10 | display: inline-block; 11 | padding: 0 4px; 12 | border-radius: 3px; 13 | line-height: 20px; 14 | margin: 2px; 15 | 16 | mark { 17 | margin: 4px 0; 18 | } 19 | } 20 | } 21 | 22 | .kwm-toggle { 23 | border-left: 2px solid #ddd; 24 | border-right: 2px solid #ddd; 25 | text-align: center; 26 | padding: .5em; 27 | background: #eee; 28 | cursor: pointer; 29 | user-select: none; 30 | border-top: 2px solid #ddd; 31 | border-bottom: 2px solid #ddd; 32 | } 33 | 34 | .kwm-show { 35 | display: none; 36 | } 37 | .kwm-hide { 38 | display: block; 39 | } 40 | 41 | .kwm-disabled { 42 | .kwm-show { 43 | display: block; 44 | } 45 | .kwm-hide { 46 | display: none; 47 | } 48 | .kwm-toggle { 49 | border-bottom: 2px solid #ddd; 50 | } 51 | .keywordmap { 52 | display: none; 53 | } 54 | } 55 | 56 | .kwt-count { 57 | background: rgba(0,0,0,.2); 58 | padding: 0 .25em; 59 | border-radius: 3px; 60 | font-size: 0.8em; 61 | margin-left: .5em; 62 | } 63 | 64 | .keywordmap-tags { 65 | border-bottom: 2px solid #efefef; 66 | border-bottom: none; 67 | 68 | &.input-is-focused { 69 | border: 2px solid #8dae28 !important; 70 | 71 | .tag, 72 | .tag-label:focus { 73 | background: #eee; 74 | } 75 | 76 | .tag.active, 77 | .tag.active .tag-label:focus { 78 | background: #8dae28; 79 | } 80 | } 81 | 82 | .tag { 83 | background: #eee; 84 | &.active { 85 | .tag-label { 86 | color: #fff; 87 | } 88 | 89 | .tag-x { 90 | color: rgba(255,255,255,.75); 91 | 92 | &:hover { 93 | color: #fff; 94 | } 95 | } 96 | } 97 | 98 | .tag-label { 99 | background: #eee; 100 | color: #000; 101 | } 102 | 103 | .tag-x { 104 | color: #777; 105 | border-left: 1px solid #fff !important; 106 | 107 | &:hover { 108 | color: #000; 109 | } 110 | } 111 | } 112 | } -------------------------------------------------------------------------------- /fields/keywordmap/assets/css/style.css: -------------------------------------------------------------------------------- 1 | .keywordmap { 2 | padding: .5em; 3 | background: #fff; 4 | border: 2px solid #ddd; 5 | border-top: none; 6 | line-height: 24px; 7 | cursor: not-allowed; } 8 | .keywordmap mark { 9 | color: #fff; 10 | display: inline-block; 11 | padding: 0 4px; 12 | border-radius: 3px; 13 | line-height: 20px; 14 | margin: 2px; } 15 | .keywordmap mark mark { 16 | margin: 4px 0; } 17 | 18 | .kwm-toggle { 19 | border-left: 2px solid #ddd; 20 | border-right: 2px solid #ddd; 21 | text-align: center; 22 | padding: .5em; 23 | background: #eee; 24 | cursor: pointer; 25 | -webkit-user-select: none; 26 | -moz-user-select: none; 27 | -ms-user-select: none; 28 | user-select: none; 29 | border-top: 2px solid #ddd; 30 | border-bottom: 2px solid #ddd; } 31 | 32 | .kwm-show { 33 | display: none; } 34 | 35 | .kwm-hide { 36 | display: block; } 37 | 38 | .kwm-disabled .kwm-show { 39 | display: block; } 40 | 41 | .kwm-disabled .kwm-hide { 42 | display: none; } 43 | 44 | .kwm-disabled .kwm-toggle { 45 | border-bottom: 2px solid #ddd; } 46 | 47 | .kwm-disabled .keywordmap { 48 | display: none; } 49 | 50 | .kwt-count { 51 | background: rgba(0, 0, 0, 0.2); 52 | padding: 0 .25em; 53 | border-radius: 3px; 54 | font-size: 0.8em; 55 | margin-left: .5em; } 56 | 57 | .keywordmap-tags { 58 | border-bottom: 2px solid #efefef; 59 | border-bottom: none; } 60 | .keywordmap-tags.input-is-focused { 61 | border: 2px solid #8dae28 !important; } 62 | .keywordmap-tags.input-is-focused .tag, 63 | .keywordmap-tags.input-is-focused .tag-label:focus { 64 | background: #eee; } 65 | .keywordmap-tags.input-is-focused .tag.active, 66 | .keywordmap-tags.input-is-focused .tag.active .tag-label:focus { 67 | background: #8dae28; } 68 | .keywordmap-tags .tag { 69 | background: #eee; } 70 | .keywordmap-tags .tag.active .tag-label { 71 | color: #fff; } 72 | .keywordmap-tags .tag.active .tag-x { 73 | color: rgba(255, 255, 255, 0.75); } 74 | .keywordmap-tags .tag.active .tag-x:hover { 75 | color: #fff; } 76 | .keywordmap-tags .tag .tag-label { 77 | background: #eee; 78 | color: #000; } 79 | .keywordmap-tags .tag .tag-x { 80 | color: #777; 81 | border-left: 1px solid #fff !important; } 82 | .keywordmap-tags .tag .tag-x:hover { 83 | color: #000; } 84 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Kirby Keyword Map 2 | 3 | *Version 0.5* - ***[Changelog](docs/changelog.md)*** 4 | 5 | Preview your important keywords in your text as a map. Good for SEO. 6 | 7 | *This plugin has nothing to to do with the meta keywords tag. It's the keywords inside your texts that are targeted.* 8 | 9 | ![](docs/preview.png) 10 | 11 | **Features** 12 | 13 | - Support for structure fields 14 | - Support for multiple keyword maps 15 | - Support for mutiple words in a keyword phrase 16 | - Support for multi languages 17 | - Highlights both keywords in tags and text. 18 | - Counters for matched words. 19 | - Will ignore these characters `-#,.!?()[]`. 20 | - Possible to show or hide the preview and just show the keywords. 21 | 22 | [**Installation instructions**](docs/install.md) 23 | 24 | ## Setup 25 | 26 | This plugin is a panel field and to use it you need to add a blueprint field. You also need a field that has a textarea. 27 | 28 | ``` 29 | fields: 30 | mytext: 31 | label: My text 32 | type: textarea 33 | keywordmap: 34 | label: Keyword Map 35 | type: keywordmap 36 | target: mytext 37 | ``` 38 | 39 | ### A field with a textarea 40 | 41 | In this case we call our textarea field `mytext` but you can call it anything. 42 | 43 | ### A field with a `keywordmap` field 44 | 45 | Our new field has two required options: 46 | 47 | - `type` needs to be `keywordmap` 48 | - `target` needs to be a field that contains a textarea, in this case it's `mytext`. 49 | 50 | ## Usage 51 | 52 | ### Add keywords 53 | 54 | Click on the top of the field to keyword phrases. Both single and multiple words are allowed in a single keyword phrase. 55 | 56 | ![](docs/tags.png) 57 | 58 | ### Write text 59 | 60 | ![](docs/text.png) 61 | 62 | ### Results 63 | 64 | See screenshot on top to see the results. 65 | 66 | ## Requirements 67 | 68 | - [**Kirby**](https://getkirby.com/) 2.4.1+ 69 | 70 | ## Disclaimer 71 | 72 | This plugin is provided "as is" with no guarantee. Use it at your own risk and always test it yourself before using it in a production environment. If you find any issues, please [create a new issue](https://github.com/jenstornell/kirby-keyword-map/issues/new). 73 | 74 | ## License 75 | 76 | [MIT](https://opensource.org/licenses/MIT) 77 | 78 | It is discouraged to use this plugin in any project that promotes racism, sexism, homophobia, animal abuse, violence or any other form of hate speech. 79 | 80 | ## Credits 81 | 82 | - [Jens Törnell](https://github.com/jenstornell) 83 | - [mark.js](https://markjs.io) - Javascript to hightlight keywords in a text 84 | - [Color Hash](https://github.com/zenozeng/color-hash) - Javascript to hash strings to color codes. -------------------------------------------------------------------------------- /fields/keywordmap/assets/js/src/script.js: -------------------------------------------------------------------------------- 1 | (function($) { 2 | $.fn.keywordmap = function() { 3 | return this.each(function() { 4 | var field = $(this); 5 | var fieldname = 'keywordmap'; 6 | var keywords = []; 7 | var target = field.attr('data-target'); 8 | 9 | if(field.data( fieldname )) { 10 | return true; 11 | } else { 12 | field.data( fieldname, true ); 13 | } 14 | 15 | kwm.setTextarea(field, target); 16 | kwm.toggle(field); 17 | 18 | field.find('input').on('change paste keyup', function() { 19 | keywords = $(this).val().split(','); 20 | kwm.mark(field, keywords); 21 | }); 22 | 23 | $('.field-name-' + target).find('textarea').on('change paste keyup', function() { 24 | kwm.setTextarea(field, target); 25 | kwm.mark(field, keywords); 26 | }); 27 | 28 | if(localStorage.getItem('kwm-disabled') !== null) { 29 | field.find('.field-content').addClass('kwm-disabled'); 30 | } 31 | }); 32 | }; 33 | 34 | var kwm = (function () { 35 | var fn = {}; 36 | 37 | fn.clear = function(field) { 38 | field.find('.keywordmap-tags [data-tag]').removeClass('active'); 39 | field.find('.keywordmap-tags [data-tag] .tag-label').attr('style', ''); 40 | field.find('.keywordmap-tags .kwt-count').remove(); 41 | field.find('.keywordmap').unmark(); 42 | }; 43 | 44 | fn.mark = function(field, keywords) { 45 | kwm.clear(field); 46 | 47 | field.find('.keywordmap-tags .kwt-count').remove(); 48 | field.find('.keywordmap').mark(keywords, { 49 | 'separateWordSearch': false, 50 | 'diacritics': false, 51 | 'accuracy': { 52 | 'value': 'exactly', 53 | 'limiters': ['-', '#', ',', '.', '!', '?', '(', ')', '[', ']'] 54 | }, 55 | 'done': function() { 56 | kwm.setTags(field); 57 | kwm.setTextareaColor(field, keywords); 58 | } 59 | }); 60 | }; 61 | 62 | fn.toggle = function(field) { 63 | field.find('.kwm-toggle').click(function() { 64 | if($(this).parent().hasClass('kwm-disabled')) { 65 | $(this).parent().removeClass('kwm-disabled'); 66 | localStorage.removeItem('kwm-disabled'); 67 | } else { 68 | $(this).parent().addClass('kwm-disabled'); 69 | localStorage.setItem('kwm-disabled', '1'); 70 | } 71 | }); 72 | }; 73 | 74 | fn.setTextareaColor = function(field, keywords) { 75 | $.each(keywords, function( index, keyword ) { 76 | var findings = field.find('mark').filter(function () { 77 | return $(this).text().toLowerCase() == keyword.toLowerCase(); 78 | }); 79 | 80 | findings.each(function(index) { 81 | var keyword = $(this).text().toLowerCase(); 82 | var style = $('[data-tag="' + keyword + '"] .tag-label').attr('style'); 83 | 84 | $(this).attr('style', style); 85 | }); 86 | 87 | }); 88 | }; 89 | 90 | fn.setTags = function(field) { 91 | var colorHash = new ColorHash(); 92 | field.find('[data-tag]').each(function(index) { 93 | var tag = $(this); 94 | var word = $(this).attr('data-tag'); 95 | var color = colorHash.hsl(word); 96 | 97 | var findings = field.find('mark').filter(function () { 98 | return $(this).text().trim().toLowerCase() == word.toLowerCase(); 99 | }); 100 | 101 | var count = findings.length; 102 | 103 | if(count > 0 ) { 104 | kwm.setTagColor(tag, word, color); 105 | if(count > 1 ) { 106 | kwm.setTagCount(tag, word, count); 107 | } 108 | } 109 | }); 110 | }; 111 | 112 | fn.setTagColor = function(tag, word, color) { 113 | tag.addClass('active'); 114 | tag.find('.tag-label').css('background-color', 'hsl(' + color[0] + ', ' + color[1]*100 + '%, ' + color[2]*100 + '%)'); 115 | }; 116 | 117 | fn.setTagCount = function(tag, word, count) { 118 | tag.find('button').html(word + '' + count + ''); 119 | }; 120 | 121 | fn.setTextarea = function(field, target) { 122 | var textarea = $('.field-name-' + target).find('textarea'); 123 | var keywordmap = field.find('.keywordmap'); 124 | if(textarea.length) { 125 | textarea = textarea.val().replace(/\n/g, '
'); 126 | keywordmap.html(textarea); 127 | } 128 | }; 129 | 130 | return fn; 131 | })(); 132 | 133 | })(jQuery); -------------------------------------------------------------------------------- /fields/keywordmap/assets/js/src/color-hash/color-hash.js: -------------------------------------------------------------------------------- 1 | !function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var o;"undefined"!=typeof window?o=window:"undefined"!=typeof global?o=global:"undefined"!=typeof self&&(o=self),o.ColorHash=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o MAX_SAFE_INTEGER) { 18 | hash = parseInt(hash / seed2); 19 | } 20 | hash = hash * seed + str.charCodeAt(i); 21 | } 22 | return hash; 23 | }; 24 | 25 | module.exports = BKDRHash; 26 | 27 | },{}],2:[function(require,module,exports){ 28 | var BKDRHash = require('./bkdr-hash'); 29 | 30 | /** 31 | * Convert RGB Array to HEX 32 | * 33 | * @param {Array} RGBArray - [R, G, B] 34 | * @returns {String} 6 digits hex starting with # 35 | */ 36 | var RGB2HEX = function(RGBArray) { 37 | var hex = '#'; 38 | RGBArray.forEach(function(value) { 39 | if (value < 16) { 40 | hex += 0; 41 | } 42 | hex += value.toString(16); 43 | }); 44 | return hex; 45 | }; 46 | 47 | /** 48 | * Convert HSL to RGB 49 | * 50 | * @see {@link http://zh.wikipedia.org/wiki/HSL和HSV色彩空间} for further information. 51 | * @param {Number} H Hue ∈ [0, 360) 52 | * @param {Number} S Saturation ∈ [0, 1] 53 | * @param {Number} L Lightness ∈ [0, 1] 54 | * @returns {Array} R, G, B ∈ [0, 255] 55 | */ 56 | var HSL2RGB = function(H, S, L) { 57 | H /= 360; 58 | 59 | var q = L < 0.5 ? L * (1 + S) : L + S - L * S; 60 | var p = 2 * L - q; 61 | 62 | return [H + 1/3, H, H - 1/3].map(function(color) { 63 | if(color < 0) { 64 | color++; 65 | } 66 | if(color > 1) { 67 | color--; 68 | } 69 | if(color < 1/6) { 70 | color = p + (q - p) * 6 * color; 71 | } else if(color < 0.5) { 72 | color = q; 73 | } else if(color < 2/3) { 74 | color = p + (q - p) * 6 * (2/3 - color); 75 | } else { 76 | color = p; 77 | } 78 | return Math.round(color * 255); 79 | }); 80 | }; 81 | 82 | /** 83 | * Color Hash Class 84 | * 85 | * @class 86 | */ 87 | var ColorHash = function(options) { 88 | options = options || {}; 89 | 90 | var LS = [options.lightness, options.saturation].map(function(param) { 91 | param = param || [0.35, 0.5, 0.65]; // note that 3 is a prime 92 | return Object.prototype.toString.call(param) === '[object Array]' ? param.concat() : [param]; 93 | }); 94 | 95 | this.L = LS[0]; 96 | this.S = LS[1]; 97 | 98 | this.hash = options.hash || BKDRHash; 99 | }; 100 | 101 | /** 102 | * Returns the hash in [h, s, l]. 103 | * Note that H ∈ [0, 360); S ∈ [0, 1]; L ∈ [0, 1]; 104 | * 105 | * @param {String} str string to hash 106 | * @returns {Array} [h, s, l] 107 | */ 108 | ColorHash.prototype.hsl = function(str) { 109 | var H, S, L; 110 | var hash = this.hash(str); 111 | 112 | H = hash % 359; // note that 359 is a prime 113 | hash = parseInt(hash / 360); 114 | S = this.S[hash % this.S.length]; 115 | hash = parseInt(hash / this.S.length); 116 | L = this.L[hash % this.L.length]; 117 | 118 | return [H, S, L]; 119 | }; 120 | 121 | /** 122 | * Returns the hash in [r, g, b]. 123 | * Note that R, G, B ∈ [0, 255] 124 | * 125 | * @param {String} str string to hash 126 | * @returns {Array} [r, g, b] 127 | */ 128 | ColorHash.prototype.rgb = function(str) { 129 | var hsl = this.hsl(str); 130 | return HSL2RGB.apply(this, hsl); 131 | }; 132 | 133 | /** 134 | * Returns the hash in hex 135 | * 136 | * @param {String} str string to hash 137 | * @returns {String} hex with # 138 | */ 139 | ColorHash.prototype.hex = function(str) { 140 | var rgb = this.rgb(str); 141 | return RGB2HEX(rgb); 142 | }; 143 | 144 | module.exports = ColorHash; 145 | 146 | },{"./bkdr-hash":1}]},{},[2])(2) 147 | }); -------------------------------------------------------------------------------- /fields/keywordmap/assets/js/dist/script.min.js: -------------------------------------------------------------------------------- 1 | function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}!function(e){e.fn.keywordmap=function(){return this.each(function(){var n=e(this),r="keywordmap",o=[],a=n.attr("data-target");return!!n.data(r)||(n.data(r,!0),t.setTextarea(n,a),t.toggle(n),n.find("input").on("change paste keyup",function(){o=e(this).val().split(","),t.mark(n,o)}),e(".field-name-"+a).find("textarea").on("change paste keyup",function(){t.setTextarea(n,a),t.mark(n,o)}),void(null!==localStorage.getItem("kwm-disabled")&&n.find(".field-content").addClass("kwm-disabled")))})};var t=function(){var n={};return n.clear=function(e){e.find(".keywordmap-tags [data-tag]").removeClass("active"),e.find(".keywordmap-tags [data-tag] .tag-label").attr("style",""),e.find(".keywordmap-tags .kwt-count").remove(),e.find(".keywordmap").unmark()},n.mark=function(e,n){t.clear(e),e.find(".keywordmap-tags .kwt-count").remove(),e.find(".keywordmap").mark(n,{separateWordSearch:!1,diacritics:!1,accuracy:{value:"exactly",limiters:["-","#",",",".","!","?","(",")","[","]"]},done:function(){t.setTags(e),t.setTextareaColor(e,n)}})},n.toggle=function(t){t.find(".kwm-toggle").click(function(){e(this).parent().hasClass("kwm-disabled")?(e(this).parent().removeClass("kwm-disabled"),localStorage.removeItem("kwm-disabled")):(e(this).parent().addClass("kwm-disabled"),localStorage.setItem("kwm-disabled","1"))})},n.setTextareaColor=function(t,n){e.each(n,function(n,r){var o=t.find("mark").filter(function(){return e(this).text().toLowerCase()==r.toLowerCase()});o.each(function(t){var n=e(this).text().toLowerCase(),r=e('[data-tag="'+n+'"] .tag-label').attr("style");e(this).attr("style",r)})})},n.setTags=function(n){var r=new ColorHash;n.find("[data-tag]").each(function(o){var a=e(this),i=e(this).attr("data-tag"),s=r.hsl(i),c=n.find("mark").filter(function(){return e(this).text().trim().toLowerCase()==i.toLowerCase()}),u=c.length;u>0&&(t.setTagColor(a,i,s),u>1&&t.setTagCount(a,i,u))})},n.setTagColor=function(e,t,n){e.addClass("active"),e.find(".tag-label").css("background-color","hsl("+n[0]+", "+100*n[1]+"%, "+100*n[2]+"%)")},n.setTagCount=function(e,t,n){e.find("button").html(t+''+n+"")},n.setTextarea=function(t,n){var r=e(".field-name-"+n).find("textarea"),o=t.find(".keywordmap");r.length&&(r=r.val().replace(/\n/g,"
"),o.html(r))},n}()}(jQuery),!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var t;"undefined"!=typeof window?t=window:"undefined"!=typeof global?t=global:"undefined"!=typeof self&&(t=self),t.ColorHash=e()}}(function(){return function e(t,n,r){function o(i,s){if(!n[i]){if(!t[i]){var c="function"==typeof require&&require;if(!s&&c)return c(i,!0);if(a)return a(i,!0);var u=new Error("Cannot find module '"+i+"'");throw u.code="MODULE_NOT_FOUND",u}var f=n[i]={exports:{}};t[i][0].call(f.exports,function(e){var n=t[i][1][e];return o(n?n:e)},f,f.exports,e,t,n,r)}return n[i].exports}for(var a="function"==typeof require&&require,i=0;io&&(r=parseInt(r/n)),r=r*t+e.charCodeAt(a);return r};t.exports=r},{}],2:[function(e,t,n){var r=e("./bkdr-hash"),o=function(e){var t="#";return e.forEach(function(e){e<16&&(t+=0),t+=e.toString(16)}),t},a=function(e,t,n){e/=360;var r=n<.5?n*(1+t):n+t-n*t,o=2*n-r;return[e+1/3,e,e-1/3].map(function(e){return e<0&&e++,e>1&&e--,e=e<1/6?o+6*(r-o)*e:e<.5?r:e<2/3?o+6*(r-o)*(2/3-e):o,Math.round(255*e)})},i=function(e){e=e||{};var t=[e.lightness,e.saturation].map(function(e){return e=e||[.35,.5,.65],"[object Array]"===Object.prototype.toString.call(e)?e.concat():[e]});this.L=t[0],this.S=t[1],this.hash=e.hash||r};i.prototype.hsl=function(e){var t,n,r,o=this.hash(e);return t=o%359,o=parseInt(o/360),n=this.S[o%this.S.length],o=parseInt(o/this.S.length),r=this.L[o%this.L.length],[t,n,r]},i.prototype.rgb=function(e){var t=this.hsl(e);return a.apply(this,t)},i.prototype.hex=function(e){var t=this.rgb(e);return o(t)},t.exports=i},{"./bkdr-hash":1}]},{},[2])(2)});var _extends=Object.assign||function(e){for(var t=1;t-1||r.indexOf("Trident")>-1)&&(this.ie=!0)}return _createClass(n,[{key:"log",value:function e(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"debug",e=this.opt.log;this.opt.debug&&"object"===("undefined"==typeof e?"undefined":_typeof(e))&&"function"==typeof e[n]&&e[n]("mark.js: "+t)}},{key:"escapeStr",value:function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}},{key:"createRegExp",value:function(e){return e=this.escapeStr(e),Object.keys(this.opt.synonyms).length&&(e=this.createSynonymsRegExp(e)),this.opt.ignoreJoiners&&(e=this.setupIgnoreJoinersRegExp(e)),this.opt.diacritics&&(e=this.createDiacriticsRegExp(e)),e=this.createMergedBlanksRegExp(e),this.opt.ignoreJoiners&&(e=this.createIgnoreJoinersRegExp(e)),e=this.createAccuracyRegExp(e)}},{key:"createSynonymsRegExp",value:function(e){var t=this.opt.synonyms,n=this.opt.caseSensitive?"":"i";for(var r in t)if(t.hasOwnProperty(r)){var o=t[r],a=this.escapeStr(r),i=this.escapeStr(o);""!==a&&""!==i&&(e=e.replace(new RegExp("("+a+"|"+i+")","gm"+n),"("+a+"|"+i+")"))}return e}},{key:"setupIgnoreJoinersRegExp",value:function(e){return e.replace(/[^(|)\\]/g,function(e,t,n){var r=n.charAt(t+1);return/[(|)\\]/.test(r)||""===r?e:e+"\0"})}},{key:"createIgnoreJoinersRegExp",value:function(e){return e.split("\0").join("[\\u00ad|\\u200b|\\u200c|\\u200d]?")}},{key:"createDiacriticsRegExp",value:function(e){var t=this.opt.caseSensitive?"":"i",n=this.opt.caseSensitive?["aàáâãäåāąă","AÀÁÂÃÄÅĀĄĂ","cçćč","CÇĆČ","dđď","DĐĎ","eèéêëěēę","EÈÉÊËĚĒĘ","iìíîïī","IÌÍÎÏĪ","lł","LŁ","nñňń","NÑŇŃ","oòóôõöøō","OÒÓÔÕÖØŌ","rř","RŘ","sšśșş","SŠŚȘŞ","tťțţ","TŤȚŢ","uùúûüůū","UÙÚÛÜŮŪ","yÿý","YŸÝ","zžżź","ZŽŻŹ"]:["aàáâãäåāąăAÀÁÂÃÄÅĀĄĂ","cçćčCÇĆČ","dđďDĐĎ","eèéêëěēęEÈÉÊËĚĒĘ","iìíîïīIÌÍÎÏĪ","lłLŁ","nñňńNÑŇŃ","oòóôõöøōOÒÓÔÕÖØŌ","rřRŘ","sšśșşSŠŚȘŞ","tťțţTŤȚŢ","uùúûüůūUÙÚÛÜŮŪ","yÿýYŸÝ","zžżźZŽŻŹ"],r=[];return e.split("").forEach(function(o){n.every(function(n){if(n.indexOf(o)!==-1){if(r.indexOf(n)>-1)return!1;e=e.replace(new RegExp("["+n+"]","gm"+t),"["+n+"]"),r.push(n)}return!0})}),e}},{key:"createMergedBlanksRegExp",value:function(e){return e.replace(/[\s]+/gim,"[\\s]+")}},{key:"createAccuracyRegExp",value:function(e){var t=this,n="!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~¡¿",r=this.opt.accuracy,o="string"==typeof r?r:r.value,a="string"==typeof r?[]:r.limiters,i="";switch(a.forEach(function(e){i+="|"+t.escapeStr(e)}),o){case"partially":default:return"()("+e+")";case"complementary":return i="\\s"+(i?i:this.escapeStr(n)),"()([^"+i+"]*"+e+"[^"+i+"]*)";case"exactly":return"(^|\\s"+i+")("+e+")(?=$|\\s"+i+")"}}},{key:"getSeparatedKeywords",value:function(e){var t=this,n=[];return e.forEach(function(e){t.opt.separateWordSearch?e.split(" ").forEach(function(e){e.trim()&&n.indexOf(e)===-1&&n.push(e)}):e.trim()&&n.indexOf(e)===-1&&n.push(e)}),{keywords:n.sort(function(e,t){return t.length-e.length}),length:n.length}}},{key:"getTextNodes",value:function(e){var t=this,n="",r=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,function(e){r.push({start:n.length,end:(n+=e.textContent).length,node:e})},function(e){return t.matchesExclude(e.parentNode)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT},function(){e({value:n,nodes:r})})}},{key:"matchesExclude",value:function(e){return o.matches(e,this.opt.exclude.concat(["script","style","title","head","html"]))}},{key:"wrapRangeInTextNode",value:function(e,n,r){var o=this.opt.element?this.opt.element:"mark",a=e.splitText(n),i=a.splitText(r-n),s=t.createElement(o);return s.setAttribute("data-markjs","true"),this.opt.className&&s.setAttribute("class",this.opt.className),s.textContent=a.textContent,a.parentNode.replaceChild(s,a),i}},{key:"wrapRangeInMappedTextNode",value:function(e,t,n,r,o){var a=this;e.nodes.every(function(i,s){var c=e.nodes[s+1];if("undefined"==typeof c||c.start>t){var u=function(){if(!r(i.node))return{v:!1};var c=t-i.start,u=(n>i.end?i.end:n)-i.start,f=e.value.substr(0,i.start),l=e.value.substr(u+i.start);return i.node=a.wrapRangeInTextNode(i.node,c,u),e.value=f+l,e.nodes.forEach(function(t,n){n>=s&&(e.nodes[n].start>0&&n!==s&&(e.nodes[n].start-=u),e.nodes[n].end-=u)}),n-=u,o(i.node.previousSibling,i.start),n>i.end?void(t=i.end):{v:!1}}();if("object"===("undefined"==typeof u?"undefined":_typeof(u)))return u.v}return!0})}},{key:"wrapMatches",value:function(e,t,n,r,o){var a=this,i=0===t?0:t+1;this.getTextNodes(function(t){t.nodes.forEach(function(t){t=t.node;for(var o=void 0;null!==(o=e.exec(t.textContent))&&""!==o[i];)if(n(o[i],t)){var s=o.index;if(0!==i)for(var c=1;c1&&void 0!==arguments[1])||arguments[1],r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:5e3;_classCallCheck(this,e),this.ctx=t,this.iframes=n,this.exclude=r,this.iframesTimeout=o}return _createClass(e,[{key:"getContexts",value:function(){var e=void 0,n=[];return e="undefined"!=typeof this.ctx&&this.ctx?NodeList.prototype.isPrototypeOf(this.ctx)?Array.prototype.slice.call(this.ctx):Array.isArray(this.ctx)?this.ctx:"string"==typeof this.ctx?Array.prototype.slice.call(t.querySelectorAll(this.ctx)):[this.ctx]:[],e.forEach(function(e){var t=n.filter(function(t){return t.contains(e)}).length>0;n.indexOf(e)!==-1||t||n.push(e)}),n}},{key:"getIframeContents",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){},r=void 0;try{var o=e.contentWindow;if(r=o.document,!o||!r)throw new Error("iframe inaccessible")}catch(e){n()}r&&t(r)}},{key:"isIframeBlank",value:function(e){var t="about:blank",n=e.getAttribute("src").trim(),r=e.contentWindow.location.href;return r===t&&n!==t&&n}},{key:"observeIframeLoad",value:function(e,t,n){var r=this,o=!1,a=null,i=function i(){if(!o){o=!0,clearTimeout(a);try{r.isIframeBlank(e)||(e.removeEventListener("load",i),r.getIframeContents(e,t,n))}catch(e){n()}}};e.addEventListener("load",i),a=setTimeout(i,this.iframesTimeout)}},{key:"onIframeReady",value:function(e,t,n){try{"complete"===e.contentWindow.document.readyState?this.isIframeBlank(e)?this.observeIframeLoad(e,t,n):this.getIframeContents(e,t,n):this.observeIframeLoad(e,t,n)}catch(e){n()}}},{key:"waitForIframes",value:function(e,t){var n=this,r=0;this.forEachIframe(e,function(){return!0},function(e){r++,n.waitForIframes(e.querySelector("html"),function(){--r||t()})},function(e){e||t()})}},{key:"forEachIframe",value:function(t,n,r){var o=this,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},i=t.querySelectorAll("iframe"),s=i.length,c=0;i=Array.prototype.slice.call(i);var u=function(){--s<=0&&a(c)};s||u(),i.forEach(function(t){e.matches(t,o.exclude)?u():o.onIframeReady(t,function(e){n(t)&&(c++,r(e)),u()},u)})}},{key:"createIterator",value:function(e,n,r){return t.createNodeIterator(e,n,r,!1)}},{key:"createInstanceOnIframe",value:function(t){return new e(t.querySelector("html"),this.iframes)}},{key:"compareNodeIframe",value:function(e,t,n){var r=e.compareDocumentPosition(n),o=Node.DOCUMENT_POSITION_PRECEDING;if(r&o){if(null===t)return!0;var a=t.compareDocumentPosition(n),i=Node.DOCUMENT_POSITION_FOLLOWING;if(a&i)return!0}return!1}},{key:"getIteratorNode",value:function(e){var t=e.previousNode(),n=void 0;return n=null===t?e.nextNode():e.nextNode()&&e.nextNode(),{prevNode:t,node:n}}},{key:"checkIframeFilter",value:function(e,t,n,r){var o=!1,a=!1;return r.forEach(function(e,t){e.val===n&&(o=t,a=e.handled)}),this.compareNodeIframe(e,t,n)?(o!==!1||a?o===!1||a||(r[o].handled=!0):r.push({val:n,handled:!0}),!0):(o===!1&&r.push({val:n,handled:!1}),!1)}},{key:"handleOpenIframes",value:function(e,t,n,r){var o=this;e.forEach(function(e){e.handled||o.getIframeContents(e.val,function(e){o.createInstanceOnIframe(e).forEachNode(t,n,r)})})}},{key:"iterateThroughNodes",value:function(e,t,n,r,o){for(var a=this,i=this.createIterator(t,e,r),s=[],c=[],u=void 0,f=void 0,l=function(){var e=a.getIteratorNode(i);return f=e.prevNode,u=e.node};l();)this.iframes&&this.forEachIframe(t,function(e){return a.checkIframeFilter(u,f,e,s)},function(t){a.createInstanceOnIframe(t).forEachNode(e,n,r)}),c.push(u);c.forEach(function(e){n(e)}),this.iframes&&this.handleOpenIframes(s,e,n,r),o()}},{key:"forEachNode",value:function(e,t,n){var r=this,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},a=this.getContexts(),i=a.length;i||o(),a.forEach(function(a){var s=function(){r.iterateThroughNodes(e,a,t,n,function(){--i<=0&&o()})};r.iframes?r.waitForIframes(a,s):s()})}}],[{key:"matches",value:function(e,t){var n="string"==typeof t?[t]:t,r=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.oMatchesSelector||e.webkitMatchesSelector;if(r){var o=!1;return n.every(function(t){return!r.call(e,t)||(o=!0,!1)}),o}return!1}}]),e}();return n.fn.mark=function(e,t){return new r(this.get()).mark(e,t),this},n.fn.markRegExp=function(e,t){return new r(this.get()).markRegExp(e,t),this},n.fn.unmark=function(e){return new r(this.get()).unmark(e),this},n},window,document); -------------------------------------------------------------------------------- /fields/keywordmap/assets/js/src/mark.js/jquery.mark.js: -------------------------------------------------------------------------------- 1 | /*!*************************************************** 2 | * mark.js v8.8.3 3 | * https://github.com/julmot/mark.js 4 | * Copyright (c) 2014–2017, Julian Motz 5 | * Released under the MIT license https://git.io/vwTVl 6 | *****************************************************/ 7 | 8 | "use strict"; 9 | 10 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; 11 | 12 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 13 | 14 | var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; 15 | 16 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 17 | 18 | (function (factory, window, document) { 19 | if (typeof define === "function" && define.amd) { 20 | define(["jquery"], function (jQuery) { 21 | return factory(window, document, jQuery); 22 | }); 23 | } else if ((typeof module === "undefined" ? "undefined" : _typeof(module)) === "object" && module.exports) { 24 | module.exports = factory(window, document, require("jquery")); 25 | } else { 26 | factory(window, document, jQuery); 27 | } 28 | })(function (window, document, $) { 29 | var Mark = function () { 30 | function Mark(ctx) { 31 | _classCallCheck(this, Mark); 32 | 33 | this.ctx = ctx; 34 | 35 | this.ie = false; 36 | var ua = window.navigator.userAgent; 37 | if (ua.indexOf("MSIE") > -1 || ua.indexOf("Trident") > -1) { 38 | this.ie = true; 39 | } 40 | } 41 | 42 | _createClass(Mark, [{ 43 | key: "log", 44 | value: function log(msg) { 45 | var level = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "debug"; 46 | 47 | var log = this.opt.log; 48 | if (!this.opt.debug) { 49 | return; 50 | } 51 | if ((typeof log === "undefined" ? "undefined" : _typeof(log)) === "object" && typeof log[level] === "function") { 52 | log[level]("mark.js: " + msg); 53 | } 54 | } 55 | }, { 56 | key: "escapeStr", 57 | value: function escapeStr(str) { 58 | return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"); 59 | } 60 | }, { 61 | key: "createRegExp", 62 | value: function createRegExp(str) { 63 | str = this.escapeStr(str); 64 | if (Object.keys(this.opt.synonyms).length) { 65 | str = this.createSynonymsRegExp(str); 66 | } 67 | if (this.opt.ignoreJoiners) { 68 | str = this.setupIgnoreJoinersRegExp(str); 69 | } 70 | if (this.opt.diacritics) { 71 | str = this.createDiacriticsRegExp(str); 72 | } 73 | str = this.createMergedBlanksRegExp(str); 74 | if (this.opt.ignoreJoiners) { 75 | str = this.createIgnoreJoinersRegExp(str); 76 | } 77 | str = this.createAccuracyRegExp(str); 78 | return str; 79 | } 80 | }, { 81 | key: "createSynonymsRegExp", 82 | value: function createSynonymsRegExp(str) { 83 | var syn = this.opt.synonyms, 84 | sens = this.opt.caseSensitive ? "" : "i"; 85 | for (var index in syn) { 86 | if (syn.hasOwnProperty(index)) { 87 | var value = syn[index], 88 | k1 = this.escapeStr(index), 89 | k2 = this.escapeStr(value); 90 | if (k1 !== "" && k2 !== "") { 91 | str = str.replace(new RegExp("(" + k1 + "|" + k2 + ")", "gm" + sens), "(" + k1 + "|" + k2 + ")"); 92 | } 93 | } 94 | } 95 | return str; 96 | } 97 | }, { 98 | key: "setupIgnoreJoinersRegExp", 99 | value: function setupIgnoreJoinersRegExp(str) { 100 | return str.replace(/[^(|)\\]/g, function (val, indx, original) { 101 | var nextChar = original.charAt(indx + 1); 102 | if (/[(|)\\]/.test(nextChar) || nextChar === "") { 103 | return val; 104 | } else { 105 | return val + "\0"; 106 | } 107 | }); 108 | } 109 | }, { 110 | key: "createIgnoreJoinersRegExp", 111 | value: function createIgnoreJoinersRegExp(str) { 112 | return str.split("\0").join("[\\u00ad|\\u200b|\\u200c|\\u200d]?"); 113 | } 114 | }, { 115 | key: "createDiacriticsRegExp", 116 | value: function createDiacriticsRegExp(str) { 117 | var sens = this.opt.caseSensitive ? "" : "i", 118 | dct = this.opt.caseSensitive ? ["aàáâãäåāąă", "AÀÁÂÃÄÅĀĄĂ", "cçćč", "CÇĆČ", "dđď", "DĐĎ", "eèéêëěēę", "EÈÉÊËĚĒĘ", "iìíîïī", "IÌÍÎÏĪ", "lł", "LŁ", "nñňń", "NÑŇŃ", "oòóôõöøō", "OÒÓÔÕÖØŌ", "rř", "RŘ", "sšśșş", "SŠŚȘŞ", "tťțţ", "TŤȚŢ", "uùúûüůū", "UÙÚÛÜŮŪ", "yÿý", "YŸÝ", "zžżź", "ZŽŻŹ"] : ["aàáâãäåāąăAÀÁÂÃÄÅĀĄĂ", "cçćčCÇĆČ", "dđďDĐĎ", "eèéêëěēęEÈÉÊËĚĒĘ", "iìíîïīIÌÍÎÏĪ", "lłLŁ", "nñňńNÑŇŃ", "oòóôõöøōOÒÓÔÕÖØŌ", "rřRŘ", "sšśșşSŠŚȘŞ", "tťțţTŤȚŢ", "uùúûüůūUÙÚÛÜŮŪ", "yÿýYŸÝ", "zžżźZŽŻŹ"]; 119 | var handled = []; 120 | str.split("").forEach(function (ch) { 121 | dct.every(function (dct) { 122 | if (dct.indexOf(ch) !== -1) { 123 | if (handled.indexOf(dct) > -1) { 124 | return false; 125 | } 126 | 127 | str = str.replace(new RegExp("[" + dct + "]", "gm" + sens), "[" + dct + "]"); 128 | handled.push(dct); 129 | } 130 | return true; 131 | }); 132 | }); 133 | return str; 134 | } 135 | }, { 136 | key: "createMergedBlanksRegExp", 137 | value: function createMergedBlanksRegExp(str) { 138 | return str.replace(/[\s]+/gmi, "[\\s]+"); 139 | } 140 | }, { 141 | key: "createAccuracyRegExp", 142 | value: function createAccuracyRegExp(str) { 143 | var _this = this; 144 | 145 | var chars = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\xA1\xBF"; 146 | var acc = this.opt.accuracy, 147 | val = typeof acc === "string" ? acc : acc.value, 148 | ls = typeof acc === "string" ? [] : acc.limiters, 149 | lsJoin = ""; 150 | ls.forEach(function (limiter) { 151 | lsJoin += "|" + _this.escapeStr(limiter); 152 | }); 153 | switch (val) { 154 | case "partially": 155 | default: 156 | return "()(" + str + ")"; 157 | case "complementary": 158 | lsJoin = "\\s" + (lsJoin ? lsJoin : this.escapeStr(chars)); 159 | return "()([^" + lsJoin + "]*" + str + "[^" + lsJoin + "]*)"; 160 | case "exactly": 161 | return "(^|\\s" + lsJoin + ")(" + str + ")(?=$|\\s" + lsJoin + ")"; 162 | } 163 | } 164 | }, { 165 | key: "getSeparatedKeywords", 166 | value: function getSeparatedKeywords(sv) { 167 | var _this2 = this; 168 | 169 | var stack = []; 170 | sv.forEach(function (kw) { 171 | if (!_this2.opt.separateWordSearch) { 172 | if (kw.trim() && stack.indexOf(kw) === -1) { 173 | stack.push(kw); 174 | } 175 | } else { 176 | kw.split(" ").forEach(function (kwSplitted) { 177 | if (kwSplitted.trim() && stack.indexOf(kwSplitted) === -1) { 178 | stack.push(kwSplitted); 179 | } 180 | }); 181 | } 182 | }); 183 | return { 184 | "keywords": stack.sort(function (a, b) { 185 | return b.length - a.length; 186 | }), 187 | "length": stack.length 188 | }; 189 | } 190 | }, { 191 | key: "getTextNodes", 192 | value: function getTextNodes(cb) { 193 | var _this3 = this; 194 | 195 | var val = "", 196 | nodes = []; 197 | this.iterator.forEachNode(NodeFilter.SHOW_TEXT, function (node) { 198 | nodes.push({ 199 | start: val.length, 200 | end: (val += node.textContent).length, 201 | node: node 202 | }); 203 | }, function (node) { 204 | if (_this3.matchesExclude(node.parentNode)) { 205 | return NodeFilter.FILTER_REJECT; 206 | } else { 207 | return NodeFilter.FILTER_ACCEPT; 208 | } 209 | }, function () { 210 | cb({ 211 | value: val, 212 | nodes: nodes 213 | }); 214 | }); 215 | } 216 | }, { 217 | key: "matchesExclude", 218 | value: function matchesExclude(el) { 219 | return DOMIterator.matches(el, this.opt.exclude.concat(["script", "style", "title", "head", "html"])); 220 | } 221 | }, { 222 | key: "wrapRangeInTextNode", 223 | value: function wrapRangeInTextNode(node, start, end) { 224 | var hEl = !this.opt.element ? "mark" : this.opt.element, 225 | startNode = node.splitText(start), 226 | ret = startNode.splitText(end - start); 227 | var repl = document.createElement(hEl); 228 | repl.setAttribute("data-markjs", "true"); 229 | if (this.opt.className) { 230 | repl.setAttribute("class", this.opt.className); 231 | } 232 | repl.textContent = startNode.textContent; 233 | startNode.parentNode.replaceChild(repl, startNode); 234 | return ret; 235 | } 236 | }, { 237 | key: "wrapRangeInMappedTextNode", 238 | value: function wrapRangeInMappedTextNode(dict, start, end, filterCb, eachCb) { 239 | var _this4 = this; 240 | 241 | dict.nodes.every(function (n, i) { 242 | var sibl = dict.nodes[i + 1]; 243 | if (typeof sibl === "undefined" || sibl.start > start) { 244 | var _ret = function () { 245 | if (!filterCb(n.node)) { 246 | return { 247 | v: false 248 | }; 249 | } 250 | 251 | var s = start - n.start, 252 | e = (end > n.end ? n.end : end) - n.start, 253 | startStr = dict.value.substr(0, n.start), 254 | endStr = dict.value.substr(e + n.start); 255 | n.node = _this4.wrapRangeInTextNode(n.node, s, e); 256 | 257 | dict.value = startStr + endStr; 258 | dict.nodes.forEach(function (k, j) { 259 | if (j >= i) { 260 | if (dict.nodes[j].start > 0 && j !== i) { 261 | dict.nodes[j].start -= e; 262 | } 263 | dict.nodes[j].end -= e; 264 | } 265 | }); 266 | end -= e; 267 | eachCb(n.node.previousSibling, n.start); 268 | if (end > n.end) { 269 | start = n.end; 270 | } else { 271 | return { 272 | v: false 273 | }; 274 | } 275 | }(); 276 | 277 | if ((typeof _ret === "undefined" ? "undefined" : _typeof(_ret)) === "object") return _ret.v; 278 | } 279 | return true; 280 | }); 281 | } 282 | }, { 283 | key: "wrapMatches", 284 | value: function wrapMatches(regex, ignoreGroups, filterCb, eachCb, endCb) { 285 | var _this5 = this; 286 | 287 | var matchIdx = ignoreGroups === 0 ? 0 : ignoreGroups + 1; 288 | this.getTextNodes(function (dict) { 289 | dict.nodes.forEach(function (node) { 290 | node = node.node; 291 | var match = void 0; 292 | while ((match = regex.exec(node.textContent)) !== null && match[matchIdx] !== "") { 293 | if (!filterCb(match[matchIdx], node)) { 294 | continue; 295 | } 296 | var pos = match.index; 297 | if (matchIdx !== 0) { 298 | for (var i = 1; i < matchIdx; i++) { 299 | pos += match[i].length; 300 | } 301 | } 302 | node = _this5.wrapRangeInTextNode(node, pos, pos + match[matchIdx].length); 303 | eachCb(node.previousSibling); 304 | 305 | regex.lastIndex = 0; 306 | } 307 | }); 308 | endCb(); 309 | }); 310 | } 311 | }, { 312 | key: "wrapMatchesAcrossElements", 313 | value: function wrapMatchesAcrossElements(regex, ignoreGroups, filterCb, eachCb, endCb) { 314 | var _this6 = this; 315 | 316 | var matchIdx = ignoreGroups === 0 ? 0 : ignoreGroups + 1; 317 | this.getTextNodes(function (dict) { 318 | var match = void 0; 319 | while ((match = regex.exec(dict.value)) !== null && match[matchIdx] !== "") { 320 | var start = match.index; 321 | if (matchIdx !== 0) { 322 | for (var i = 1; i < matchIdx; i++) { 323 | start += match[i].length; 324 | } 325 | } 326 | var end = start + match[matchIdx].length; 327 | 328 | _this6.wrapRangeInMappedTextNode(dict, start, end, function (node) { 329 | return filterCb(match[matchIdx], node); 330 | }, function (node, lastIndex) { 331 | regex.lastIndex = lastIndex; 332 | eachCb(node); 333 | }); 334 | } 335 | endCb(); 336 | }); 337 | } 338 | }, { 339 | key: "unwrapMatches", 340 | value: function unwrapMatches(node) { 341 | var parent = node.parentNode; 342 | var docFrag = document.createDocumentFragment(); 343 | while (node.firstChild) { 344 | docFrag.appendChild(node.removeChild(node.firstChild)); 345 | } 346 | parent.replaceChild(docFrag, node); 347 | if (!this.ie) { 348 | parent.normalize(); 349 | } else { 350 | this.normalizeTextNode(parent); 351 | } 352 | } 353 | }, { 354 | key: "normalizeTextNode", 355 | value: function normalizeTextNode(node) { 356 | if (!node) { 357 | return; 358 | } 359 | if (node.nodeType === 3) { 360 | while (node.nextSibling && node.nextSibling.nodeType === 3) { 361 | node.nodeValue += node.nextSibling.nodeValue; 362 | node.parentNode.removeChild(node.nextSibling); 363 | } 364 | } else { 365 | this.normalizeTextNode(node.firstChild); 366 | } 367 | this.normalizeTextNode(node.nextSibling); 368 | } 369 | }, { 370 | key: "markRegExp", 371 | value: function markRegExp(regexp, opt) { 372 | var _this7 = this; 373 | 374 | this.opt = opt; 375 | this.log("Searching with expression \"" + regexp + "\""); 376 | var totalMatches = 0, 377 | fn = "wrapMatches"; 378 | var eachCb = function eachCb(element) { 379 | totalMatches++; 380 | _this7.opt.each(element); 381 | }; 382 | if (this.opt.acrossElements) { 383 | fn = "wrapMatchesAcrossElements"; 384 | } 385 | this[fn](regexp, this.opt.ignoreGroups, function (match, node) { 386 | return _this7.opt.filter(node, match, totalMatches); 387 | }, eachCb, function () { 388 | if (totalMatches === 0) { 389 | _this7.opt.noMatch(regexp); 390 | } 391 | _this7.opt.done(totalMatches); 392 | }); 393 | } 394 | }, { 395 | key: "mark", 396 | value: function mark(sv, opt) { 397 | var _this8 = this; 398 | 399 | this.opt = opt; 400 | var totalMatches = 0, 401 | fn = "wrapMatches"; 402 | 403 | var _getSeparatedKeywords = this.getSeparatedKeywords(typeof sv === "string" ? [sv] : sv), 404 | kwArr = _getSeparatedKeywords.keywords, 405 | kwArrLen = _getSeparatedKeywords.length, 406 | sens = this.opt.caseSensitive ? "" : "i", 407 | handler = function handler(kw) { 408 | var regex = new RegExp(_this8.createRegExp(kw), "gm" + sens), 409 | matches = 0; 410 | _this8.log("Searching with expression \"" + regex + "\""); 411 | _this8[fn](regex, 1, function (term, node) { 412 | return _this8.opt.filter(node, kw, totalMatches, matches); 413 | }, function (element) { 414 | matches++; 415 | totalMatches++; 416 | _this8.opt.each(element); 417 | }, function () { 418 | if (matches === 0) { 419 | _this8.opt.noMatch(kw); 420 | } 421 | if (kwArr[kwArrLen - 1] === kw) { 422 | _this8.opt.done(totalMatches); 423 | } else { 424 | handler(kwArr[kwArr.indexOf(kw) + 1]); 425 | } 426 | }); 427 | }; 428 | 429 | if (this.opt.acrossElements) { 430 | fn = "wrapMatchesAcrossElements"; 431 | } 432 | if (kwArrLen === 0) { 433 | this.opt.done(totalMatches); 434 | } else { 435 | handler(kwArr[0]); 436 | } 437 | } 438 | }, { 439 | key: "unmark", 440 | value: function unmark(opt) { 441 | var _this9 = this; 442 | 443 | this.opt = opt; 444 | var sel = this.opt.element ? this.opt.element : "*"; 445 | sel += "[data-markjs]"; 446 | if (this.opt.className) { 447 | sel += "." + this.opt.className; 448 | } 449 | this.log("Removal selector \"" + sel + "\""); 450 | this.iterator.forEachNode(NodeFilter.SHOW_ELEMENT, function (node) { 451 | _this9.unwrapMatches(node); 452 | }, function (node) { 453 | var matchesSel = DOMIterator.matches(node, sel), 454 | matchesExclude = _this9.matchesExclude(node); 455 | if (!matchesSel || matchesExclude) { 456 | return NodeFilter.FILTER_REJECT; 457 | } else { 458 | return NodeFilter.FILTER_ACCEPT; 459 | } 460 | }, this.opt.done); 461 | } 462 | }, { 463 | key: "opt", 464 | set: function set(val) { 465 | this._opt = _extends({}, { 466 | "element": "", 467 | "className": "", 468 | "exclude": [], 469 | "iframes": false, 470 | "iframesTimeout": 5000, 471 | "separateWordSearch": true, 472 | "diacritics": true, 473 | "synonyms": {}, 474 | "accuracy": "partially", 475 | "acrossElements": false, 476 | "caseSensitive": false, 477 | "ignoreJoiners": false, 478 | "ignoreGroups": 0, 479 | "each": function each() {}, 480 | "noMatch": function noMatch() {}, 481 | "filter": function filter() { 482 | return true; 483 | }, 484 | "done": function done() {}, 485 | "debug": false, 486 | "log": window.console 487 | }, val); 488 | }, 489 | get: function get() { 490 | return this._opt; 491 | } 492 | }, { 493 | key: "iterator", 494 | get: function get() { 495 | if (!this._iterator) { 496 | this._iterator = new DOMIterator(this.ctx, this.opt.iframes, this.opt.exclude, this.opt.iframesTimeout); 497 | } 498 | return this._iterator; 499 | } 500 | }]); 501 | 502 | return Mark; 503 | }(); 504 | 505 | var DOMIterator = function () { 506 | function DOMIterator(ctx) { 507 | var iframes = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; 508 | var exclude = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; 509 | var iframesTimeout = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 5000; 510 | 511 | _classCallCheck(this, DOMIterator); 512 | 513 | this.ctx = ctx; 514 | 515 | this.iframes = iframes; 516 | 517 | this.exclude = exclude; 518 | 519 | this.iframesTimeout = iframesTimeout; 520 | } 521 | 522 | _createClass(DOMIterator, [{ 523 | key: "getContexts", 524 | value: function getContexts() { 525 | var ctx = void 0, 526 | filteredCtx = []; 527 | if (typeof this.ctx === "undefined" || !this.ctx) { 528 | ctx = []; 529 | } else if (NodeList.prototype.isPrototypeOf(this.ctx)) { 530 | ctx = Array.prototype.slice.call(this.ctx); 531 | } else if (Array.isArray(this.ctx)) { 532 | ctx = this.ctx; 533 | } else if (typeof this.ctx === "string") { 534 | ctx = Array.prototype.slice.call(document.querySelectorAll(this.ctx)); 535 | } else { 536 | ctx = [this.ctx]; 537 | } 538 | 539 | ctx.forEach(function (ctx) { 540 | var isDescendant = filteredCtx.filter(function (contexts) { 541 | return contexts.contains(ctx); 542 | }).length > 0; 543 | if (filteredCtx.indexOf(ctx) === -1 && !isDescendant) { 544 | filteredCtx.push(ctx); 545 | } 546 | }); 547 | return filteredCtx; 548 | } 549 | }, { 550 | key: "getIframeContents", 551 | value: function getIframeContents(ifr, successFn) { 552 | var errorFn = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : function () {}; 553 | 554 | var doc = void 0; 555 | try { 556 | var ifrWin = ifr.contentWindow; 557 | doc = ifrWin.document; 558 | if (!ifrWin || !doc) { 559 | throw new Error("iframe inaccessible"); 560 | } 561 | } catch (e) { 562 | errorFn(); 563 | } 564 | if (doc) { 565 | successFn(doc); 566 | } 567 | } 568 | }, { 569 | key: "isIframeBlank", 570 | value: function isIframeBlank(ifr) { 571 | var bl = "about:blank", 572 | src = ifr.getAttribute("src").trim(), 573 | href = ifr.contentWindow.location.href; 574 | return href === bl && src !== bl && src; 575 | } 576 | }, { 577 | key: "observeIframeLoad", 578 | value: function observeIframeLoad(ifr, successFn, errorFn) { 579 | var _this10 = this; 580 | 581 | var called = false, 582 | tout = null; 583 | var listener = function listener() { 584 | if (called) { 585 | return; 586 | } 587 | called = true; 588 | clearTimeout(tout); 589 | try { 590 | if (!_this10.isIframeBlank(ifr)) { 591 | ifr.removeEventListener("load", listener); 592 | _this10.getIframeContents(ifr, successFn, errorFn); 593 | } 594 | } catch (e) { 595 | errorFn(); 596 | } 597 | }; 598 | ifr.addEventListener("load", listener); 599 | tout = setTimeout(listener, this.iframesTimeout); 600 | } 601 | }, { 602 | key: "onIframeReady", 603 | value: function onIframeReady(ifr, successFn, errorFn) { 604 | try { 605 | if (ifr.contentWindow.document.readyState === "complete") { 606 | if (this.isIframeBlank(ifr)) { 607 | this.observeIframeLoad(ifr, successFn, errorFn); 608 | } else { 609 | this.getIframeContents(ifr, successFn, errorFn); 610 | } 611 | } else { 612 | this.observeIframeLoad(ifr, successFn, errorFn); 613 | } 614 | } catch (e) { 615 | errorFn(); 616 | } 617 | } 618 | }, { 619 | key: "waitForIframes", 620 | value: function waitForIframes(ctx, done) { 621 | var _this11 = this; 622 | 623 | var eachCalled = 0; 624 | this.forEachIframe(ctx, function () { 625 | return true; 626 | }, function (ifr) { 627 | eachCalled++; 628 | _this11.waitForIframes(ifr.querySelector("html"), function () { 629 | if (! --eachCalled) { 630 | done(); 631 | } 632 | }); 633 | }, function (handled) { 634 | if (!handled) { 635 | done(); 636 | } 637 | }); 638 | } 639 | }, { 640 | key: "forEachIframe", 641 | value: function forEachIframe(ctx, filter, each) { 642 | var _this12 = this; 643 | 644 | var end = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : function () {}; 645 | 646 | var ifr = ctx.querySelectorAll("iframe"), 647 | open = ifr.length, 648 | handled = 0; 649 | ifr = Array.prototype.slice.call(ifr); 650 | var checkEnd = function checkEnd() { 651 | if (--open <= 0) { 652 | end(handled); 653 | } 654 | }; 655 | if (!open) { 656 | checkEnd(); 657 | } 658 | ifr.forEach(function (ifr) { 659 | if (DOMIterator.matches(ifr, _this12.exclude)) { 660 | checkEnd(); 661 | } else { 662 | _this12.onIframeReady(ifr, function (con) { 663 | if (filter(ifr)) { 664 | handled++; 665 | each(con); 666 | } 667 | checkEnd(); 668 | }, checkEnd); 669 | } 670 | }); 671 | } 672 | }, { 673 | key: "createIterator", 674 | value: function createIterator(ctx, whatToShow, filter) { 675 | return document.createNodeIterator(ctx, whatToShow, filter, false); 676 | } 677 | }, { 678 | key: "createInstanceOnIframe", 679 | value: function createInstanceOnIframe(contents) { 680 | return new DOMIterator(contents.querySelector("html"), this.iframes); 681 | } 682 | }, { 683 | key: "compareNodeIframe", 684 | value: function compareNodeIframe(node, prevNode, ifr) { 685 | var compCurr = node.compareDocumentPosition(ifr), 686 | prev = Node.DOCUMENT_POSITION_PRECEDING; 687 | if (compCurr & prev) { 688 | if (prevNode !== null) { 689 | var compPrev = prevNode.compareDocumentPosition(ifr), 690 | after = Node.DOCUMENT_POSITION_FOLLOWING; 691 | if (compPrev & after) { 692 | return true; 693 | } 694 | } else { 695 | return true; 696 | } 697 | } 698 | return false; 699 | } 700 | }, { 701 | key: "getIteratorNode", 702 | value: function getIteratorNode(itr) { 703 | var prevNode = itr.previousNode(); 704 | var node = void 0; 705 | if (prevNode === null) { 706 | node = itr.nextNode(); 707 | } else { 708 | node = itr.nextNode() && itr.nextNode(); 709 | } 710 | return { 711 | prevNode: prevNode, 712 | node: node 713 | }; 714 | } 715 | }, { 716 | key: "checkIframeFilter", 717 | value: function checkIframeFilter(node, prevNode, currIfr, ifr) { 718 | var key = false, 719 | handled = false; 720 | ifr.forEach(function (ifrDict, i) { 721 | if (ifrDict.val === currIfr) { 722 | key = i; 723 | handled = ifrDict.handled; 724 | } 725 | }); 726 | if (this.compareNodeIframe(node, prevNode, currIfr)) { 727 | if (key === false && !handled) { 728 | ifr.push({ 729 | val: currIfr, 730 | handled: true 731 | }); 732 | } else if (key !== false && !handled) { 733 | ifr[key].handled = true; 734 | } 735 | return true; 736 | } 737 | if (key === false) { 738 | ifr.push({ 739 | val: currIfr, 740 | handled: false 741 | }); 742 | } 743 | return false; 744 | } 745 | }, { 746 | key: "handleOpenIframes", 747 | value: function handleOpenIframes(ifr, whatToShow, eCb, fCb) { 748 | var _this13 = this; 749 | 750 | ifr.forEach(function (ifrDict) { 751 | if (!ifrDict.handled) { 752 | _this13.getIframeContents(ifrDict.val, function (con) { 753 | _this13.createInstanceOnIframe(con).forEachNode(whatToShow, eCb, fCb); 754 | }); 755 | } 756 | }); 757 | } 758 | }, { 759 | key: "iterateThroughNodes", 760 | value: function iterateThroughNodes(whatToShow, ctx, eachCb, filterCb, doneCb) { 761 | var _this14 = this; 762 | 763 | var itr = this.createIterator(ctx, whatToShow, filterCb); 764 | var ifr = [], 765 | elements = [], 766 | node = void 0, 767 | prevNode = void 0, 768 | retrieveNodes = function retrieveNodes() { 769 | var _getIteratorNode = _this14.getIteratorNode(itr); 770 | 771 | prevNode = _getIteratorNode.prevNode; 772 | node = _getIteratorNode.node; 773 | 774 | return node; 775 | }; 776 | while (retrieveNodes()) { 777 | if (this.iframes) { 778 | this.forEachIframe(ctx, function (currIfr) { 779 | return _this14.checkIframeFilter(node, prevNode, currIfr, ifr); 780 | }, function (con) { 781 | _this14.createInstanceOnIframe(con).forEachNode(whatToShow, eachCb, filterCb); 782 | }); 783 | } 784 | 785 | elements.push(node); 786 | } 787 | elements.forEach(function (node) { 788 | eachCb(node); 789 | }); 790 | if (this.iframes) { 791 | this.handleOpenIframes(ifr, whatToShow, eachCb, filterCb); 792 | } 793 | doneCb(); 794 | } 795 | }, { 796 | key: "forEachNode", 797 | value: function forEachNode(whatToShow, each, filter) { 798 | var _this15 = this; 799 | 800 | var done = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : function () {}; 801 | 802 | var contexts = this.getContexts(); 803 | var open = contexts.length; 804 | if (!open) { 805 | done(); 806 | } 807 | contexts.forEach(function (ctx) { 808 | var ready = function ready() { 809 | _this15.iterateThroughNodes(whatToShow, ctx, each, filter, function () { 810 | if (--open <= 0) { 811 | done(); 812 | } 813 | }); 814 | }; 815 | 816 | if (_this15.iframes) { 817 | _this15.waitForIframes(ctx, ready); 818 | } else { 819 | ready(); 820 | } 821 | }); 822 | } 823 | }], [{ 824 | key: "matches", 825 | value: function matches(element, selector) { 826 | var selectors = typeof selector === "string" ? [selector] : selector, 827 | fn = element.matches || element.matchesSelector || element.msMatchesSelector || element.mozMatchesSelector || element.oMatchesSelector || element.webkitMatchesSelector; 828 | if (fn) { 829 | var match = false; 830 | selectors.every(function (sel) { 831 | if (fn.call(element, sel)) { 832 | match = true; 833 | return false; 834 | } 835 | return true; 836 | }); 837 | return match; 838 | } else { 839 | return false; 840 | } 841 | } 842 | }]); 843 | 844 | return DOMIterator; 845 | }(); 846 | 847 | $.fn.mark = function (sv, opt) { 848 | new Mark(this.get()).mark(sv, opt); 849 | return this; 850 | }; 851 | $.fn.markRegExp = function (regexp, opt) { 852 | new Mark(this.get()).markRegExp(regexp, opt); 853 | return this; 854 | }; 855 | $.fn.unmark = function (opt) { 856 | new Mark(this.get()).unmark(opt); 857 | return this; 858 | }; 859 | return $; 860 | }, window, document); --------------------------------------------------------------------------------