I tested this code in its strict html format, and the jQuery works.
Then I coded answers to this question in WordPress as 1) a plugin and 2) loaded from functions.php. In each case, the jQuery fails.
The problem appears, to my untrained eye, to be related to the Javascript. Specifically because the method "toggle(element)" is a global object at the time that "$.each" is executed. Somewhere along the line, I believe that the two need to be inter-linked but despite spending the better part of a day on this, it is beyond my ability. Of course, there's the risk of PEBCAK.
The content as displayed (proving that $.each has run successfully)
The content HTML
Chrome Console before clicking on the text:
Chrome Console after clicking on a blank work in the text
The Plugin consists of:
1 - The Plugin file (vocab.php)
2 - The Plugin Javascript file (vocab.js)
3 - The Plugin Template content file (vocab-template.php)
4 - The Page Template (page-vocab.php) (Template name = Vocab Test)
Plus One Standard WordPress Page, template = "Vocab Test"
The Plugin file (vocab.php)
<?php
/*
Plugin Name: a_Stackoverflow_Vocab test
*/
// 01 - Define the filesystem paths for the plugin
if ( ! defined( 'WP_CONTENT_URL' ) )
define( 'WP_CONTENT_URL', get_option( 'siteurl' ) . '/wp-content' );
if ( ! defined( 'WP_CONTENT_DIR' ) )
define( 'WP_CONTENT_DIR', ABSPATH . 'wp-content' );
if ( ! defined( 'WP_PLUGIN_URL' ) )
define( 'WP_PLUGIN_URL', WP_CONTENT_URL. '/plugins' );
if ( ! defined( 'WP_PLUGIN_DIR' ) )
define( 'WP_PLUGIN_DIR', WP_CONTENT_DIR . '/plugins' );
define( 'VOCAB_DIR', plugin_dir_path( __FILE__ ) );
define( 'VOCAB_URL', plugin_dir_url( __FILE__ ) );
// 02 - Enqueue scripts and styles for the plugin.
function vocab_scripts() {
if (!is_admin()) {
if (is_page(array('vocab'))) {
wp_enqueue_script( 'jquery' );
wp_register_script('vocabjs', VOCAB_URL . 'vocab.js', array( 'jquery'),NULL);
wp_enqueue_script('vocabjs');
}
}
}
add_action( 'wp_enqueue_scripts', 'vocab_scripts' );
// Calls to key files: template layout
require("vocab-template.php");
?>
The Javascript file (vocab.js)
jQuery(document).ready(function ($) {
var words = [];
words.push('vocabulary');
words.push('lexicon');
words.push('lexicons');
function toggle(element) {
if (element.innerHTML.split('_').join('').trim().length === 0) {
element.innerHTML = element.getAttribute("word");
} else {
element.innerHTML = "_______";
}
}
$.each(words, function(index, value) {
var replacestr = new RegExp('\\b'+value+'\\b', "g");
$("p#demo:contains('" + value + "')").html(function(_, html) {
return html.replace(replacestr, ' <span class = "smallcaps" word="' + value + '" onclick="toggle(this)">_______</span>')
});
});
});
The Plugin Template content file (vocab-template.php)
<?php
/*
* function to deliver template
*/
function insert_vocab_template(){
?>
<div id="page">
<!-- start div page -->
<h1>Vocabulary Test</h1>
<div id="cover_content">
<h2>Test content</h2>
<p id="demo">A vocabulary is a list of words that an individual knows or uses regularly. vocabulary is different from lexicon because vocabulary is about what an individual or group of people know, whereas lexicon is about the language itself. In this paragraph, lexicons is a new word that's added, so don't forget to push 'lexicons' in your array.</p>
</div>
<!-- end cover_content -->
</div>
<!-- end #page -->
<?php
}
?>
The Page Template (page-vocab.php)
<?php /* Template Name: Vocab Test */ ?>
<?php
get_header(); ?>
<div id="primary" class="content-area">
<main id="main" class="site-main" role="main">
<!-- page -->
<?php
$myoutput = insert_vocab_template();
echo $myoutput;
?>
</main><!-- .site-main -->
</div><!-- .primary -->
<?php get_sidebar(); ?>
<?php get_footer(); ?>
Alternative via Functions.php (in a child theme)
1 - Enqueue function in Functions.php
2 - The Javascript file (themes/childtheme/js) - vocab2.js (identical to plugin version)
3 - The Page Template (page-vocab2.php) (Template name = Vocab2 Test)
Plus One Standard WordPress Page, template = "Vocab Test2"
Note: in this version, the paragraph of text (with id="demo") was included in the WordPress page as content.
Extract from Functions.php
// enqueue jquery and script
function vocab2_scripts() {
if (!is_admin()) {
if (is_page(array('vocab2'))) {
wp_enqueue_script('jquery');
wp_enqueue_script('vocab2js', get_stylesheet_directory_uri(). '/js/vocab2.js', array( 'jquery' ));
}
}
}
add_action( 'wp_enqueue_scripts', 'vocab2_scripts' );
The Javascript file (themes/childtheme/js) - vocab2.js
jQuery(document).ready(function ($) {
var words = [];
words.push('vocabulary');
words.push('lexicon');
words.push('lexicons');
function toggle(element) {
if (element.innerHTML.split('_').join('').trim().length === 0) {
element.innerHTML = element.getAttribute("word");
} else {
element.innerHTML = "_______";
}
}
$.each(words, function(index, value) {
var replacestr = new RegExp('\\b'+value+'\\b', "g");
$("p#demo:contains('" + value + "')").html(function(_, html) {
return html.replace(replacestr, ' <span class = "smallcaps" word="' + value + '" onclick="toggle(this)">_______</span>')
});
});
});
The Page Template (page-vocab2.php) (Template name = Vocab2 Test)
<?php /* Template Name: Vocab Test2 */ ?>
<?php
get_header(); ?>
<div id="primary" class="content-area">
<main id="main" class="site-main" role="main">
<!-- page -->
<?php
while ( have_posts() ) : the_post();
?>
<article id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
<header class="entry-header">
<?php the_title( '<h1 class="entry-title">', '</h1>' ); ?>
</header><!-- .entry-header -->
<div class="entry-content">
<?php the_content();?>
</div><!-- .entry-content -->
</article><!-- #post-## -->
<?php
// End of the loop.
endwhile;
?>
</main><!-- .site-main -->
</div><!-- .content-area -->
<?php get_sidebar(); ?>
<?php get_footer(); ?>
UPDATE:
I can now get the code to work by calling "toggle" from with the "$.each" statement but the Console is still giving errors - now changed to:
"Uncaught TypeError: Cannot read property 'innerHTML' of undefined"
The Javascript file now looks like this:
function toggle(element) {
if (element.innerHTML.split('_').join('').trim().length === 0) {
element.innerHTML = element.getAttribute("word");
} else {
element.innerHTML = "_______";
}
}
jQuery(document).ready(function ($) {
var words = [];
words.push('vocabulary');
words.push('lexicon');
words.push('lexicons');
$.each(words, function(index, value) {
var replacestr = new RegExp('\\b'+value+'\\b', "g");
$("p#demo:contains('" + value + "')").html(function(_, html) {
return html.replace(replacestr, ' <span class = "smallcaps" word="' + value + '" onclick="toggle(this)">_______</span>')
});
});
toggle();
});
wp_head()
somewhere between<head>
and</head>