We have used the TinyMCE editor with "non editable" plugin. we tried to delete the non editable content, it is deleted. How to restrict the delete(delete/backspace) action for non editable content?
Below is my code:
tinymce.init({
selector: "#myeditablediv",
plugins: "advlist table lists image paste link pagebreak noneditable help",
noneditable_noneditable_class: "mceNonEditable",
menubar: false,
inline: true,
height: 500,
paste_data_images: true,
toolbar_sticky: true,
toolbar:
"bold italic underline | superscript subscript | formatselect | bullist | code pagebreak | link image | COC | table | removeformat | help",
formats: {
editable: {
inline: "span",
styles: { borderBottom: "2px solid gray" },
classes: "mceEditable"
}
},
setup: function (editor) {
editor.ui.registry.addButton("COC", {
text: "<b style='font-size:large;font-weight:bold;'>{CC}</b>",
tooltip: "CopyToClipBoard",
onAction: function (api) {
editor.execCommand("Copy");
}
});
},
toolbar_mode: "floating"
});
.demo-inline {
box-shadow: 0 2px 8px 0 rgba(0, 0, 0, 0.2);
text-align: left;
line-height: 1.3;
background-color: #ffffff;
text-align: left;
vertical-align: top;
padding: 20px 20px 20px 20px;
}
.demo-inline .container {
background-color: #fafafa;
margin: -20px -20px 0 -20px;
padding: 20px;
}
.demo-inline ul,
.demo-inline ol {
padding-left: 20px;
}
.demo-inline ul {
list-style: disc;
}
.demo-inline ol {
list-style: decimal;
}
.demo-inline a {
text-decoration: underline;
}
.demo-inline img {
display: block;
margin-left: auto;
margin-right: auto;
padding: 0px 10px 10px 10px;
}
.demo-inline textarea {
display: none;
}
.demo-inline *[contentEditable="true"]:focus,
.demo-inline *[contentEditable="true"]:hover {
outline: 2px solid #2276d2;
}
#myeditablediv {
margin-top: 20px;
font-family: "Calibri";
font-size: 16px;
line-height: 1.1em;
}
/*Component Editable*/
div.FixedComponent {
text-align: center;
background-color: #d8d8d8;
padding: 10px;
}
div.FixedComponent::before {
content: attr(data-displayname);
}
div[data-prefix]::before {
content: attr(data-prefix);
color: #1f477d !important;
font-weight: bold;
float: left;
display: inline-block;
margin-right: 3px;
}
.componentSuffix::after {
content: " ]";
color: #1f477d !important;
font-weight: bold;
}
div[data-type="content"] {
min-height: 23px;
display: inline;
}
div.ComponentWrapper:focus {
outline: dotted;
}
<script src="https://cdn.tiny.cloud/1/qagffr3pkuv17a8on1afax661irst1hbr4e6tbv888sz91jc/tinymce/5/tinymce.min.js"></script>
<div class="demo-inline">
<div id="myeditablediv">
Hi tiny
<p class='mceNonEditable'> <b> This is a non editable content</b>
</p>
<p> <span class='mceNonEditable'> <b>This part is non editable</b> </span>
This is a editable content
<span class='mceNonEditable'> <b>This part is non editable</b> </span>
</p>
</div>
</div>
TinyMCE's noneditable plugin is designed to make a block of content non-editiable, but not non-deletable. Rather it treats the entire section of non-editable content as a single character.
To stop content from being deleted with the keyboard, you could use Tiny's event handling structure to look for certain key presses and then interrupt/stop them. Here is a very simple example of how to do that:
http://fiddle.tinymce.com/Mvhaab
You would need to expand this to look at where the cursor is located in the content, and if the result of the keypress would delete something you want to preserve, stop the keypress only in those situations.
Note that this approach will not keep content from being deleted via other methods, such as by removing it as part of a larger selection.
Wrote an Angular service which so far works alright, possibly needs some tweaking for edge cases. nonDeletableSelectors contains the CSS selectors denoting elements which should be non-deletable. I noticed that there is apparently a TinyMCE bug with non-editable elements though, so the code is more complex than I think it should be.
import {Injectable} from '#angular/core';
#Injectable({
providedIn: 'root'
})
export class EditorPreventDeleteService {
constructor() { }
public nonDeletableSelectors = ['.mceNonEditable'];
public preventDelete(editor) {
let self = this;
editor.on('keydown', function(event) {
if (self.keyWillDelete(event)) {
let range = editor.selection.getRng(), selection = editor.selection.getSel();
if (!range.collapsed)
return self.checkSelection(editor, event);
else if (event.keyCode == 8)
self.checkBackspace(editor, event, selection);
else if (event.keyCode == 46)
self.checkDelete(editor, event, selection);
}
return true;
});
editor.on('beforeSetContent', event => {
return self.checkSelection(editor, event);
});
editor.on('dragstart', event => {
if (self.checkNode(event.target, true))
self.cancelEvent(event);
});
}
protected checkNode(node, includeChildren = true) {
if (node && node.nodeType !== Node.TEXT_NODE)
for (let nonDeletableSelector of this.nonDeletableSelectors)
if (node.matches(nonDeletableSelector)
|| (includeChildren && node.querySelectorAll(nonDeletableSelector).length > 0))
return true;
return false;
}
protected checkSelection(editor, event) {
const selectedHTMLString = editor.selection.getContent({format : 'html'});
const selectedHTML = new DOMParser().parseFromString(selectedHTMLString, 'text/html').documentElement;
if (this.checkNode(selectedHTML))
return this.cancelEvent(event);
return true;
}
protected checkBackspace(editor, event, selection) {
if (selection.anchorOffset === 0 && this.getPrefixContent(editor, selection).length === 0)
return this.cancelEvent(event);
this.checkCaretDeletion(editor, event, selection, false);
}
protected checkDelete(editor, event, selection) {
this.checkCaretDeletion(editor, event, selection, true);
}
protected checkCaretDeletion(editor, event, selection, forwards = true) { // https://developer.mozilla.org/en-US/docs/Web/API/Selection
let borderingElement = forwards ? selection.anchorNode.nextSibling : selection.anchorNode.previousSibling;
if (selection.anchorNode.nodeType === Node.TEXT_NODE) {
if (this.getTrailingText(selection, forwards, false).length > 0)
return; // not at the border of a text element
} else if (selection.anchorOffset !== (forwards ? selection.anchorNode.childNodes.length : 0)
&& this.trimZeroWidthSpaces(selection.anchorNode.textContent).length > 0
&& this.checkNode(selection.anchorNode.childNodes.item(selection.anchorOffset + (forwards?0:1))))
return this.cancelEvent(event); // not at the border of anchor, anchor not empty, only neighbouring child is deleted
if (this.checkNode(selection.anchorNode) || this.checkNode(borderingElement))
this.cancelEvent(event);
}
protected getPrefixContent(editor, selection) {
let currentRange = editor.selection.getRng(1), tempRange = currentRange.cloneRange();
tempRange.setStartBefore(editor.getBody().childNodes.item(0));
tempRange.setEndBefore(selection.anchorNode);
editor.selection.setRng(tempRange);
let content = editor.selection.getContent({format: 'html'});
editor.selection.setRng(currentRange);
return this.trimZeroWidthSpaces(content.trim());
}
protected getTrailingText(selection, forwards = true, includeSiblings = false) {
let trailer = '', appendTrailer = function(text) { forwards ? trailer += text : trailer = text + trailer; }
if (selection.anchorNode.nodeType === Node.TEXT_NODE) {
let text = selection.anchorNode.textContent;
appendTrailer(forwards ? text.substr(selection.anchorOffset) : text.substr(0, selection.anchorOffset));
} else {
for (let i=selection.anchorOffset ; i>=0 && i<selection.anchorNode.childNodes.length ; i+=(forwards?-1:1))
appendTrailer(selection.anchorNode.childNodes.item(i).textContent);
}
if (includeSiblings) {
let sibling = selection.anchorNode.previousSibling;
while (sibling) {
appendTrailer(sibling.textContent);
sibling = sibling.previousSibling;
}
}
return this.trimZeroWidthSpaces(trailer);
}
protected cancelEvent(event) {
event.preventDefault();
event.stopPropagation();
return false;
}
protected keyWillDelete(evt) {
let c = evt.keyCode;
if (evt.ctrlKey)
return evt.key == 'x' || [8, 46].includes(c);
return [8, 9, 13, 46].includes(c)
|| this.inRange(c, 48, 57)
|| this.inRange(c, 65, 90)
|| this.inRange(c, 96, 111)
|| this.inRange(c, 186, 192)
|| this.inRange(c, 219, 222);
}
protected inRange(val, min, max) {
return val >= min && val <= max;
}
protected trimZeroWidthSpaces(text: string) {
return text.replace(/[\u200B-\u200D\uFEFF]/g, '');
}
}
Related
I've made a menu that reveals a drop down menu when you click or touch it. At least that's what happens when you select the word 'Menu2' but unfortunately it's not what happens when you select the words 'Menu3'.
On Menu3, for some reason my code is not recognising the selection of the anchor element and then as a consequence the id of that anchor element is not being passed to the functions which will make the sub-menu appear and disappear.
The strangest thing is that when I replace the 'else if' statement with an 'if' statement the menu under 'Menu2' will appear when I select 'Menu3'!
The thing I took from this was that the querySelectorAll method and the For loop are working. It remains a mystery me why the third menu choice can't be selected.
My question is can anyone work why the menu below 'Menu3' is not opening and closing?
The listeners in the javascript code are activated when the window is loaded.
var timeout = 500;
var closetimer = 0;
var ddmenuitem = 0;
function listen(elem, evnt, func) {
if (elem.addEventListener) { //W3C DOMS.
elem.addEventListener(evnt, func, false);
} else if (elem.attachEvent) { //IE DOM 7
var r = elem.attachEvent("on" + evnt, func);
return r;
}
}
function attachListeners() {
var selectors = document.querySelectorAll("a#a2, a#a3");
for (var i = 0; i < selectors.length; i++) {
selectors[i].addEventListener("focus", function(event) {
var id_of_clicked_element = event.target.id
});
if (id_of_clicked_element = 'a2') {
var touch_div = document.getElementById(id_of_clicked_element);
// return false;
} else if (id_of_clicked_element = 'a3') {
touch_div = document.getElementById(id_of_clicked_element);
//return false;
}
}
listen(touch_div, 'touchstart', function(event) {
// get new layer and show it
event.preventDefault();
mopen(id_of_clicked_element);
}, false);
listen(touch_div, 'mouseover', function(event) {
// get new layer and show it
mopen(id_of_clicked_element);
}, false);
listen(touch_div, 'click', function(event) {
// get new layer and show it
mopen(id_of_clicked_element);
}, false);
}
function m1View() {
var y = document.getElementById('m1');
if (y.style.visibility === 'hidden') {
y.style.visibility = 'visible';
} else {
y.style.visibility = 'hidden';
}
}
function m2View() {
var z = document.getElementById('m2');
if (z.style.visibility === 'hidden') {
z.style.visibility = 'visible';
} else {
z.style.visibility = 'hidden';
}
}
// open hidden layer
function mopen(x) { // get new layer and show it
var openmenu = x;
if (openmenu = 'a2') {
m1View();
} else if (openmenu = 'a3') {
m2View();
}
}
window.onload = attachListeners;
#ddm {
margin: 0;
padding: 0;
z-index: 30
}
#ddm li {
margin: 0;
padding: 0;
list-style: none;
float: left;
font: bold 14px arial
}
#ddm li a {
display: block;
margin: 0 0 0 0;
padding: 12px 17px;
width: 130px;
background: #CC0066;
color: #FFF;
text-align: center;
text-decoration: none
}
#ddm li a:hover {
background: #CC0066
}
#ddm div {
position: absolute;
visibility: hidden;
margin: 0;
padding: 0;
background: #EAEBD8;
border: 1px solid #5970B2
}
#ddm div a {
position: relative;
display: block;
margin: 0;
padding: 5px 10px;
width: 130px;
white-space: nowrap;
text-align: left;
text-decoration: none;
background: #EAEBD8;
color: #5C124A;
font: 13px arial;
border: 1px solid #CC0066
}
#ddm div a:hover {
background: #CC0066;
color: #FFF
}
<ul id="ddm">
<li>Menu1</li>
<li>
Menu2
<div id="m1">
Dropdown 1.1
Dropdown 1.2
Dropdown 1.3
Dropdown 1.4
Dropdown 1.5
Dropdown 1.6
</div>
</li>
<li>
Menu3
<div id="m2">
Menu4
</div>
</li>
<li>Menu5</li>
<li>Menu6</li>
</ul>
<div style="clear:both"></div>
A JSfiddle can be found here: https://jsfiddle.net/Webfeet/z9x6Ly6k/27/
Thank you for any help anyone can provide.
NewWeb
I'd suggest a couple of things. First, like Leo Li suggested, I think you may have overcomplicated this a little. For instance, you could replace your attachListeners function with something like this:
function attachListeners() {
var selectors = document.querySelectorAll("a#a2, a#a3");
for (var i = 0; i < selectors.length; i++) {
selectors[i].addEventListener('touchstart', function(event){
event.preventDefault();
mopen(event.target.id);
}, false);
selectors[i].addEventListener('mouseover', function(event){
event.preventDefault();
mopen(event.target.id);
}, false);
selectors[i].addEventListener('click', function(event){
event.preventDefault();
mopen(event.target.id);
}, false);
}
}
But, besides that, one of the biggest problems is in the mopen() function. Instead of checking the value being passed in for x, you're reassigning it. Just switch the equals signs with triple equals, like this:
if (openmenu === 'a2') {
m1View();
} else if (openmenu === 'a3') {
m2View();
}
It's still probably not quite what you're looking for but here's a fork of your JSfiddle with my changes - https://jsfiddle.net/n90ryvfd/
Hope that helps!
function makeCategory() {
getList = document.getElementById("list");
cat = document.createElement("div");
cat.setAttribute("class", "cat");
getList.appendChild(cat);
cat.innerHTML =
'<input type="text" name="name"/><span class="removeButton" onclick= "remove(this)">-</span><br><span class="makeSubCat" onclick="makeSubCategory(this)">+Category</span>';
}
function remove(z) {
document.getElementById("list").removeChild(z.parentNode);
}
function makeSubCategory(i) {
y = document.createElement("input");
x = document.getElementsByClassName("cat");
x[i].appendChild(y);
}
Can't figure out how i can append child on each element of the class with "onclick". It's not working with "for loop" - it's always appends to the latest div. It's only works when i specify the number of class element.
Demo Outline
Reworked the HTML tags into a real Description List or <dl>
Instead of trying to manipulate multiple elements recursively, we will drive the functions by the click event
Use of Event Delegation saves us a ton of extra code. Only one eventListener() is needed for an unlimited number of <button>s and <input>s.
Template Literal was used in lieu of string literal
insertAdjacentHTML() played an important part of the add() function
Details are commented within the demo
Demo
// Reference the Description List dl#list
var dock = document.getElementById("list");
/* Callback function
|| if the clicked button is NOT dl#list...
|| - tgt/e.target is the clicked <button>
|| - if tgt has .add, then call add()...
|| else if tgt has .rem...
|| cat is its parent (.cat)
|| - Get div.cat parent and remove .cat
*/
function mod(e, dock) {
if (e.target !== e.currentTarget) {
var tgt = e.target;
if (tgt.className === 'add') {
add.call(this, dock);
} else if (tgt.className === 'rem') {
var cat = tgt.parentNode;
cat.parentNode.removeChild(cat);
} else return;
}
}
/* Register the ancestor of all of the .cat
|| and <button>s. (dl#list).
|| By doing this there's no need to addEventListeners
|| for every <button>
*/
dock.addEventListener('click', function(e) {
mod(e, this);
}, false);
/* This function expression takes a string (in this
|| case the string is a Template Literal.) and
|| parses it into HTML as it inserts it at a
|| position determined by the first parameter:
|| "beforeend"
|| (exactly like append)
*/
var add = function(dock) {
var cat = `<dd class='cat'>
<input name="name" type='text'>
<button class="rem">-</button>
<button class="add">+</button>
</dd>`;
dock.insertAdjacentHTML('beforeend', cat);
};
#list {
margin: 20px;
border: 2px ridge gold;
background: rgba(0, 0, 0, .3);
padding: 5px 10px 15px;
}
dt {
font: 700 20px/1 Consolas;
color: gold;
background: rgba(0, 0, 0, .5);
padding: 5px;
}
dd {
font-size: 16px;
color: #fff;
background: rgba(0, 0, 0, .5);
padding: 5px;
margin: 8px 4px 8px 0;
}
input,
button {
width: 10%;
font: inherit;
display: inline-block;
}
input[type='text'] {
width: 76%;
}
<dl id='list'>
<dt>Category List</dt>
<dd class='cat'>
<input name="name" type='text'>
<button class="add">+</button>
</dd>
</dl>
I am trying to show a description when hovering over an option in a select list, however, I am having trouble getting the code to recognize when hovering.
Relevant code:
Select chunk of form:
<select name="optionList" id="optionList" onclick="rankFeatures(false)" size="5"></select>
<select name="ranks" id="ranks" size="5"></select>
Manipulating selects (arrays defined earlier):
function rankFeatures(create) {
var $optionList = $("#optionList");
var $ranks = $("#ranks");
if(create == true) {
for(i=0; i<5; i++){
$optionList.append(features[i]);
};
}
else {
var index = $optionList.val();
$('#optionList option:selected').remove();
$ranks.append(features[index]);
};
}
This all works. It all falls apart when I try to deal with hovering over options:
$(document).ready(
function (event) {
$('select').hover(function(e) {
var $target = $(e.target);
if($target.is('option')) {
alert('yeah!');
};
})
})
I found that code while searching through Stack Exchange, yet I am having no luck getting it to work. The alert occurs when I click on an option. If I don't move the mouse and close the alert by hitting enter, it goes away. If I close out with the mouse a second alert window pops up. Just moving the mouse around the select occasionally results in an alert box popping up.
I have tried targeting the options directly, but have had little success with that. How do I get the alert to pop up if I hover over an option?
You can use the mouseenter event.
And you do not have to use all this code to check if the element is an option.
Just use the .on() syntax to delegate to the select element.
$(document).ready(function(event) {
$('select').on('mouseenter','option',function(e) {
alert('yeah');
// this refers to the option so you can do this.value if you need..
});
});
Demo at http://jsfiddle.net/AjfE8/
try with mouseover. Its working for me. Hover also working only when the focus comes out from the optionlist(like mouseout).
function (event) {
$('select').mouseover(function(e) {
var $target = $(e.target);
if($target.is('option')) {
alert('yeah!');
};
})
})
You don't need to rap in in a function, I could never get it to work this way. When taking it out works perfect. Also used mouseover because hover is ran when leaving the target.
$('option').mouseover(function(e) {
var $target = $(e.target);
if($target.is('option')) {
console.log('yeah!');
};
})
Fiddle to see it working. Changed it to console so you don't get spammed with alerts. http://jsfiddle.net/HMDqb/
That you want is to detect hover event on option element, not on select:
$(document).ready(
function (event) {
$('#optionList option').hover(function(e) {
console.log(e.target);
});
})
I have the same issue, but none of the solutions are working.
$("select").on('mouseenter','option',function(e) {
$("#show-me").show();
});
$("select").on('mouseleave','option',function(e) {
$("#show-me").hide();
});
$("option").mouseover(function(e) {
var $target = $(e.target);
if($target.is('option')) {
alert('yeah!');
};
});
Here my jsfiddle https://jsfiddle.net/ajg99wsm/
I would recommend to go for a customized variant if you like to ease
capture hover events
change hover color
same behavior for "drop down" and "all items" view
plus you can have
resizeable list
individual switching between single selection and multiple selection mode
more individual css-ing
multiple lines for option items
Just have a look to the sample attached.
$(document).ready(function() {
$('.custopt').addClass('liunsel');
$(".custopt, .custcont").on("mouseover", function(e) {
if ($(this).attr("id") == "crnk") {
$("#ranks").css("display", "block")
} else {
$(this).addClass("lihover");
}
})
$(".custopt, .custcont").on("mouseout", function(e) {
if ($(this).attr("id") == "crnk") {
$("#ranks").css("display", "none")
} else {
$(this).removeClass("lihover");
}
})
$(".custopt").on("click", function(e) {
$(".custopt").removeClass("lihover");
if ($("#btsm").val() == "ssm") {
//single select mode
$(".custopt").removeClass("lisel");
$(".custopt").addClass("liunsel");
$(this).removeClass("liunsel");
$(this).addClass("lisel");
} else if ($("#btsm").val() == "msm") {
//multiple select mode
if ($(this).is(".lisel")) {
$(this).addClass("liunsel");
$(this).removeClass("lisel");
} else {
$(this).addClass("lisel");
$(this).removeClass("liunsel");
}
}
updCustHead();
});
$(".custbtn").on("click", function() {
if ($(this).val() == "ssm") {
$(this).val("msm");
$(this).text("switch to single-select mode")
} else {
$(this).val("ssm");
$(this).text("switch to multi-select mode")
$(".custopt").removeClass("lisel");
$(".custopt").addClass("liunsel");
}
updCustHead();
});
function updCustHead() {
if ($("#btsm").val() == "ssm") {
if ($(".lisel").length <= 0) {
$("#hrnk").text("current selected option");
} else {
$("#hrnk").text($(".lisel").text());
}
} else {
var numopt = +$(".lisel").length,
allopt = $(".custopt").length;
$("#hrnk").text(numopt + " of " + allopt + " selected option" + (allopt > 1 || numopt === 0 ? 's' : ''));
}
}
});
body {
text-align: center;
}
.lisel {
background-color: yellow;
}
.liunsel {
background-color: lightgray;
}
.lihover {
background-color: coral;
}
.custopt {
margin: .2em 0 .2em 0;
padding: .1em .3em .1em .3em;
text-align: left;
font-size: .7em;
border-radius: .4em;
}
.custlist,
.custhead {
width: 100%;
text-align: left;
padding: .1em;
border: LightSeaGreen solid .2em;
border-radius: .4em;
height: 4em;
overflow-y: auto;
resize: vertical;
user-select: none;
}
.custlist {
display: none;
cursor: pointer;
}
.custhead {
resize: none;
height: 2.2em;
font-size: .7em;
padding: .1em .4em .1em .4em;
margin-bottom: -.2em;
width: 95%;
}
.custcont {
width: 7em;
padding: .5em 1em .6em .5em;
/* border: blue solid .2em; */
margin: 1em auto 1em auto;
}
.custbtn {
font-size: .7em;
width: 105%;
}
h3 {
margin: 1em 0 .5em .3em;
font-weight: bold;
font-size: 1em;
}
ul {
margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h3>
customized selectable, hoverable resizeable dropdown with multi-line, single-selection and multiple-selection support
</h3>
<div id="crnk" class="custcont">
<div>
<button id="btsm" class="custbtn" value="ssm">switch to multi-select mode</button>
</div>
<div id="hrnk" class="custhead">
current selected option
</div>
<ul id="ranks" class="custlist">
<li class="custopt">option one</li>
<li class="custopt">option two</li>
<li class="custopt">another third long option</li>
<li class="custopt">another fourth long option</li>
</ul>
</div>
In my project I'm using jqPagination plugin. I really like the functionality, but I was wondering if it's possible to customize it in the way that max-page number always appears outside of the input box. Here is my link to the jsfiddle https://jsfiddle.net/webIra7/hqz90Lwj/1/
<div class="some-container">
<div class="loaded-page">First page </div>
<div class="loaded-page">Second page</div>
<div class="loaded-page">Third page</div>
</div>
<div class="gigantic pagination">
‹
<input class="pagenumber" type="text" readonly="readonly" />
›
</div>
You can access to plugin properties like this:
($('.pagination').jqPagination('option', 'max_page'))
Check the fiddle to see it working: https://jsfiddle.net/ivan0013/hqz90Lwj/5/
According to the customization section of the documentation for the jqPagination plugin, you can pass a page_string to the options. The default value is 'Page {current_page} of {max_page}'.
You could change the page_string in the options to be just 'Page {current_page}', then put the max page number in a separate HTML element outside of the pagination element.
See updated fiddle here.
You can calculate the maxPageNumber outside the jqPagination object and set this value to a span element after the next button.
To change the page format string you can use:
page_string: 'Page {current_page}',
Do not copy or include the src code of plugin, you may include it with:
<script src="https://rawgit.com/beneverard/jqPagination/master/js/jquery.jqpagination.min.js"></script>
The snippet:
$(document).ready(function () {
// hide all but the first of our paragraphs
$('.some-container div.loaded-page:not(:first)').hide();
// compute the maxPageNumber
var maxPageNumber = $('.some-container div.loaded-page').length;
// set this value as you wish:
$('#maxPageNumber').text(maxPageNumber);
// initialize the jqPagination
$('.pagination').jqPagination({
max_page: maxPageNumber,
page_string: 'Page {current_page}', // change the string format
paged: function (page) {
// a new 'page' has been requested
// hide all paragraphs
$('.some-container div.loaded-page').hide();
// but show the one we want
$($('.some-container div.loaded-page')[page - 1]).show();
}
});
});
.pagenumber::-ms-clear {
width: 0;
height: 0;
}
.pagination {
display: inline-block;
border-radius: 3px;
}
.pagination a {
display: block;
float: left;
width: 20px;
height: 20px;
outline: none;
border-right: 1px solid #CDCDCD;
border-left: 1px solid #CDCDCD;
color: #555555;
vertical-align: middle;
text-align: center;
text-decoration: none;
font-size: 15px;
font-family: Helvetica, Arial, sans-serif;
/* ATTN: need a better font stack */
background-color: #f3f3f3;
}
.pagination a:hover, .pagination a:focus, .pagination a:active {
background-color: #006699;
color: white;
border: 1px solid #cdcdcd;
}
.pagination a.previous:hover, .pagination a.previous:focus, .pagination a.previous:active, .pagination a.next:hover,
.pagination a.next:focus, .pagination a.next:active, .pagination a.disabled, .pagination a.disabled:hover,
.pagination a.disabled:focus, .pagination a.disabled:active {
background-color: #006699;
color: #A8A8A8;
cursor: default;
color: white;
}
.pagination a:first-child {
border: none;
border-radius: 2px 0 0 2px;
}
.pagination a:last-child {
border: none;
border-radius: 0 2px 2px 0;
}
.pagination input {
float: left;
margin: 0;
padding: 0;
width: 115px;
height: 20px;
outline: none;
border: none;
vertical-align: middle;
text-align: center;
}
/* gigantic class for demo purposes */
.gigantic.pagination {
margin: 0;
}
.gigantic.pagination a {
font-size: 30px;
background-color: #eee;
border-radius: 0;
color: #006699;
float: left;
height: 35px;
width: 35px;
line-height: 30px;
border: solid 1px #ccc;
}
.gigantic.pagination input {
width: 120px;
font-size: 15px;
font-family: Helvetica, Arial, sans-serif;
margin: 0;
padding: 7px 0;
}
/* log element for demo purposes */
.log {
display: none;
background-color: #EDEDED;
height: 300px;
width: 524px;
overflow: auto;
margin-left: 0;
list-style: none;
padding: 10px;
}
.log li {
margin-top: 0;
margin-bottom: 5px;
}
<script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
<script src="https://rawgit.com/beneverard/jqPagination/master/js/jquery.jqpagination.min.js"></script>
<div class="some-container">
<div class="loaded-page">First page </div>
<div class="loaded-page">Second page</div>
<div class="loaded-page">Third page</div>
</div>
<div class="gigantic pagination">
‹
<input class="pagenumber" type="text" readonly="readonly" />
›
<span id="maxPageNumber" style='margin-top: 1.00em;margin-left:1.25em; display:inline-block;'/>
</div>
HTML:
<div class="some-container">
<div class="loaded-page">First page </div>
<div class="loaded-page">Second page</div>
<div class="loaded-page">Third page</div>
</div>
<div class="gigantic pagination">
‹
<input class="pagenumber" type="text" readonly="readonly" />
›
<input class="maxPageNumber" type="text" readonly="readonly" id="maxPag" />
</div>
JS:
(function(e) {
"use strict";
e.jqPagination = function(t, n) {
var r = this;
r.$el = e(t);
r.el = t;
r.$input = r.$el.find(".pagenumber");
r.$el.data("jqPagination", r);
r.init = function() {
r.options = e.extend({}, e.jqPagination.defaultOptions, n);
r.options.max_page === null && (r.$input.data("max-page") !== undefined ? r.options.max_page = r.$input.data("max-page") : r.options.max_page = 1);
r.$input.data("current-page") !== undefined && r.isNumber(r.$input.data("current-page")) && (r.options.current_page = r.$input.data("current-page"));
r.$input.removeAttr("readonly");
r.updateInput(!0);
r.$input.on("focus.jqPagination mouseup.jqPagination", function(t) {
if (t.type === "focus") {
var n = parseInt(r.options.current_page, 10);
e(this).val(n).select()
}
if (t.type === "mouseup") return !1
});
r.$input.on("blur.jqPagination keydown.jqPagination", function(t) {
var n = e(this),
i = parseInt(r.options.current_page, 10);
if (t.keyCode === 27) {
n.val(i);
n.blur()
}
t.keyCode === 13 && n.blur();
t.type === "blur" && r.setPage(n.val())
});
r.$el.on("click.jqPagination", "a", function(t) {
var n = e(this);
if (n.hasClass("disabled")) return !1;
if (!t.metaKey && !t.ctrlKey) {
t.preventDefault();
r.setPage(n.data("action"))
}
})
};
r.setPage = function(e, t) {
if (e === undefined) return r.options.current_page;
var n = parseInt(r.options.current_page, 10),
i = parseInt(r.options.max_page, 10);
if (isNaN(parseInt(e, 10))) switch (e) {
case "first":
e = 1;
break;
case "prev":
case "previous":
e = n - 1;
break;
case "next":
e = n + 1;
break;
case "last":
e = i
}
e = parseInt(e, 10);
if (isNaN(e) || e < 1 || e > i) {
r.setInputValue(n);
return !1
}
r.options.current_page = e;
r.$input.data("current-page", e);
r.updateInput(t)
};
r.setMaxPage = function(e, t) {
if (e === undefined) return r.options.max_page;
if (!r.isNumber(e)) {
console.error("jqPagination: max_page is not a number");
return !1
}
if (e < r.options.current_page) {
console.error("jqPagination: max_page lower than current_page");
return !1
}
r.options.max_page = e;
r.$input.data("max-page", e);
r.updateInput(t)
};
r.updateInput = function(e) {
var t = parseInt(r.options.current_page, 10);
r.setInputValue(t);
r.setLinks(t);
e !== !0 && r.options.paged(t)
};
r.setInputValue = function(e) {
var t = r.options.page_string,
n = r.options.max_page;
t = t.replace("{current_page}", e).replace("{max_page}", n);
r.$input.val(t);
$("#maxPag").val("of " + n);
};
r.isNumber = function(e) {
return !isNaN(parseFloat(e)) && isFinite(e)
};
r.setLinks = function(e) {
var t = r.options.link_string,
n = parseInt(r.options.current_page, 10),
i = parseInt(r.options.max_page, 10);
if (t !== "") {
var s = n - 1;
s < 1 && (s = 1);
var o = n + 1;
o > i && (o = i);
r.$el.find("a.first").attr("href", t.replace("{page_number}", "1"));
r.$el.find("a.prev, a.previous").attr("href", t.replace("{page_number}", s));
r.$el.find("a.next").attr("href", t.replace("{page_number}", o));
r.$el.find("a.last").attr("href", t.replace("{page_number}", i))
}
r.$el.find("a").removeClass("disabled");
n === i && r.$el.find(".next, .last").addClass("disabled");
n === 1 && r.$el.find(".previous, .first").addClass("disabled")
};
r.callMethod = function(t, n, i) {
switch (t.toLowerCase()) {
case "option":
if (i === undefined && typeof n != "object") return r.options[n];
var s = {
trigger: !0
},
o = !1;
e.isPlainObject(n) && !i ? e.extend(s, n) : s[n] = i;
var u = s.trigger === !1;
s.current_page !== undefined && (o = r.setPage(s.current_page, u));
s.max_page !== undefined && (o = r.setMaxPage(s.max_page, u));
o === !1 && console.error("jqPagination: cannot get / set option " + n);
return o;
case "destroy":
r.$el.off(".jqPagination").find("*").off(".jqPagination");
break;
default:
console.error('jqPagination: method "' + t + '" does not exist');
return !1
}
};
r.init()
};
e.jqPagination.defaultOptions = {
current_page: 1,
link_string: "",
max_page: null,
page_string: "Page {current_page}",
page_string2: "of {max_page}",
paged: function() {}
};
e.fn.jqPagination = function() {
var t = this,
n = e(t),
r = Array.prototype.slice.call(arguments),
i = !1;
if (typeof r[0] == "string") {
r[2] === undefined ? i = n.first().data("jqPagination").callMethod(r[0], r[1]) : n.each(function() {
i = e(this).data("jqPagination").callMethod(r[0], r[1], r[2]);
});
return i
}
t.each(function() {
new e.jqPagination(this, r[0])
})
}
})(jQuery);
if (!console) {
var console = {},
func = function() {
return !1
};
console.log = func;
console.info = func;
console.warn = func;
console.error = func
};
$(document).ready(function() {
// hide all but the first of our paragraphs
$('.some-container div.loaded-page:not(:first)').hide();
$('.pagination').jqPagination({
max_page : $('.some-container div.loaded-page').length,
paged : function(page) {
// a new 'page' has been requested
// hide all paragraphs
$('.some-container div.loaded-page').hide();
// but show the one we want
$($('.some-container div.loaded-page')[page - 1]).show();
}
});
$('.pagination2').jqPagination({
max_page : $('.some-container div.loaded-page').length,
paged : function(page) {
// a new 'page' has been requested
// hide all paragraphs
$('.some-container div.loaded-page').hide();
// but show the one we want
$($('.some-container div.loaded-page')[page - 1]).show();
}
});
});
CSS:
.pagenumber::-ms-clear{
width: 0;
height: 0;
}
.pagination{
display: inline-block;
border-radius: 3px;
}
I include <input class="maxPageNumber" type="text" readonly="readonly" id="maxPag" /> change page_string: "Page {current_page} of {max_page}" to page_string: "Page {current_page}", page_string2: "of {max_page}" and include $("#maxPag").val("of" + n);
I have been writing my own Lightbox script (to learn more about jQuery).
My code for the captions are as follows (the problem is that the captions are the same on every image):
close.click(function(c) {
c.preventDefault();
if (hideScrollbars == "1") {
$('body').css({'overflow' : 'auto'});
}
overlay.add(container).fadeOut('normal');
$('#caption').animate({
opacity: 0.0
}, "5000", function() {
$('div').remove('#caption');
});
});
$(prev.add(next)).click(function(c) {
c.preventDefault();
$('div').remove('#caption')
areThereAlts = "";
var current = parseInt(links.filter('.selected').attr('lb-position'),10);
var to = $(this).is('.prev') ? links.eq(current - 1) : links.eq(current + 1);
if(!to.size()) {
to = $(this).is('.prev') ? links.eq(links.size() - 1) : links.eq(0);
}
if(to.size()) {
to.click();
}
});
So, I found out what was wrong (Cheers Deng!), further down the code I had the following function (I had to add "link" into the remove caption code):
links.each(function(index) {
var link = $(this);
link.click(function(c) {
c.preventDefault();
if (hideScrollbars == "1") {
$('body').css({'overflow' : 'hidden'});
}
open(link.attr('href'));
links.filter('.selected').removeClass('selected');
link.addClass('selected');
var areThereAlts = $(".thumb", link).attr("alt"); //"link" needed to be added here
//alert(areThereAlts);
if (areThereAlts !== "") {
container.append('<div id="caption" style="display: block; font-family: Verdana; background-color: white; padding: 4px 5px 10px 5px; top -10px; width: 100%; height: 25px; vertical-align: middle; -moz-border-radius-topleft: 10px; -moz-border-radius-topright: 10px; color: #3f3f3f;"><font color="#3f3f3f">'+areThereAlts+'</font></div>') //caption
}
});
link.attr({'lb-position': index});
});