Is there a way to hide() unmatched search elements using mark.js? After reading the documentation I initially thought that I could use the "noMatch" option to write a custom function to hide the parent div of unmatched text, but it's not working as hoped for.
For example, if I am using mark.js to search and highlight "Lorem" in the following:
<div class="panel-body context">
<h2>Lorem</h2>
<div>
<p>ipsum</p>
<p>lorem</p>
</div>
<h2>ipsum</h2>
<div>
<p>ipsum</p>
<p>lorem</p>
</div>
</div>
How can I get it to only return the matched elements like so?
<div class="panel-body context">
<h2><span="highlight">Lorem</span><h2>
<div>
<p><span="highlight">lorem</span></p>
</div>
<div>
<p><span="highlight">lorem</span></p>
</div>
</div>
Here's my current code block:
$(function() {
var mark = function() {
// Read the keyword
var keyword = $("input[name='search-keyword']").val();
// Determine selected options
var options = {
"element": "span",
"className": "highlight",
"separateWordSearch": false,
"noMatch": function(term) {
term.hide(); // WHERE I HOPED I COULD ADD HIDE LOGIC
}
}
// Remove previous marked elements and mark
// the new keyword inside the context
$(".panel-body context").unmark({
done: function() {
$(".panel-body context").mark(keyword, options);
}
});
};
$("input[name='search-keyword']").on("input", mark);
});
EDIT Here's my altered jsfiddle from the mark.js examples for a better example of what I'm attempting to do. Thanks for any assistance ahead of time!
$(function() {
var mark = function() {
// Read the keyword
var keyword = $("input[name='keyword']").val();
var keyword2 = $("input[name='keyword2']").val();
// Remove previous marked elements and mark
// the new keyword inside the context
$(".context").unmark({
done: function() {
$(".context").mark(keyword).mark(keyword2, {className: 'secondary'});
$("#binddata").text(keyword);
}
});
};
$("input[name^='keyword']").on("input", mark);
});
mark {
padding: 0;
background-color:yellow;
}
mark.secondary {
padding: 0;
background-color: orange;
}
<link href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.6/superhero/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/mark.js/8.6.0/jquery.mark.min.js"></script>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<input type="text" name="keyword"><input type="text" name="keyword2">
<span id="binddata">Bind Character</span>
<div class="context">
The fox went over the fence
<h2>Lorem<h2>
<div>
<p>ipsum</p>
<p>lorem</p>
</div>
<h2>ipsum</h2>
<div>
<p>ipsum</p>
<p>lorem</p>
</div>
</div>
Related
I'm trying to add a Class to an img when the mouse is over an element and remove the class when the mouse is no longer over the element. I'm using object literal notation. I can't see to select the correct image, can anyone see where i'm going wrong?
let Cc = {
bindEvent: function() {
$('.title.em-below').hover( function() {
let selectedtitle = $(this);
Cc.scaleThumbnail(selectedtitle);
})
},
scaleThumbnail: function(selectedtitle) {
let $thumbnail = selectedtitle.siblings('.image-thumbnail')
let img = $thumbnail.children('img');
console.log(img);
img.addClass('thumbnail-active');
img.removeClass('thumbnail-active');
},
}
.thumbnail-active {
transform: scale(1.1);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="title em-below">
Title
</div>
<a class="image-thumbnail">
<div class="wide-thumbnail em-below">
<img src="https://via.placeholder.com/350x150"/>
</div>
</a>
</div>
You need to call CC.bindEvent() to bind the event handler. And your hover function needs to toggle the class, not add it and then immediately remove it.
The img element is not a child of $thumbnail, it's the grandchild. Use .find() instead of .children().
let Cc = {
bindEvent: function() {
$('.title.em-below').hover( function() {
let selectedtitle = $(this);
Cc.scaleThumbnail(selectedtitle);
})
},
scaleThumbnail: function(selectedtitle) {
let $thumbnail = selectedtitle.siblings('.image-thumbnail')
let img = $thumbnail.find('img');
//console.log(img.attr('src'));
img.toggleClass('thumbnail-active');
},
}
Cc.bindEvent();
.thumbnail-active {
transform: scale(1.1);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="title em-below">
Title
</div>
<a class="image-thumbnail">
<div class="wide-thumbnail em-below">
<img src="https://via.placeholder.com/350x150"/>
</div>
</a>
</div>
The problem is with this line, because of which the img tag is not captured.
$thumbnail.children('img');
.children only traverses its immediate child which is .wide-thumbnail.em-below.
Use .find instead
$thumbnail.find('img');
I'm posting my html and directive code. I have two spans, which I have attached ng-click to. On ng-click I want to check the classes of their parents parent item (.parent-portlet), but what I have so far is not working correctly as all of the parent portlets get selected instead of only the current one.
<div class="parent-portlet {{portlet.class}} {{portlet.class2}}" ng-mouseenter="hoverIn($event)" ng-mouseleave="hoverOut($event)">
<div class="portlet-titlebar" ng-click="toggleCollapsed($event)">
<span class="remove" ng-click="removePortlet(portlet)">
Remove
</span>
<span class="add-back" ng-click="addPortlet(portlet)">
Add Back
</span>
</div>
</div>
this is what I have in my directive:
scope.removePortlet = function(portlet) {
var port = $('.remove').parent().parent();
port.addClass('removed');
port.addClass('edit-portlet');
};
scope.addPortlet = function(portlet) {
var port = $('.add-back').parent().parent();
if (portlet.hasClass('removed')) {
port.removeClass('removed');
port.removeClass('edit-portlet');
}
};
The problem with this code is that var portlet catches all of the portlets(parents) and I want to catch only the one related to the click action. How can I achieve that? I tried to pass this to my jquery select like so:
var portlet = $('.add-back', this).parent().parent();
but that didn't work. Any ideas how this can be achieved?
Thanks in advance.
Pass in the $event to the ng-click like this:
<span ng-click="removePortlet($event)"></span>
Then, just modify your code like this:
scope.removePortlet = function(ev) {
var port = $(ev.target).parent().parent();
port.addClass('removed');
port.addClass('edit-portlet');
};
scope.addPortlet = function(ev) {
var port = $(ev.target).parent().parent();
if ($(ev.target).hasClass('removed')) {
port.removeClass('removed');
port.removeClass('edit-portlet');
}
};
Grabbing the "event's target" will ensure that you are only addressing the item that was actually clicked. And note that angular uses $event to pass the event to a function.
I would also clean it up a bit combining the class modification lines and targeting the specific parent (in case you ever modify the DOM) using .closest():
scope.removePortlet = function(ev) {
var port = $(ev.target).closest('.parent-portlet');
port.addClass('removed, edit-portlet');
};
scope.addPortlet = function(ev) {
var port = $(ev.target).closest('.parent-portlet');
if (portlet.hasClass('removed')) {
port.removeClass('removed, edit-portlet');
}
};
You can inject the $element to your controller, then, use it as the context for the $ selector.
angular.module('app', []).controller('ctrl', function($scope, $element) {
$scope.addPortlet = function(portlet) {
console.log($('.add-back', $element));
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div class="parent-portlet">
<div class="portlet-titlebar" ng-click="toggleCollapsed($event)">
<span class="remove" ng-click="removePortlet(portlet)">
Remove
</span>
<span class="add-back" ng-click="addPortlet(portlet)">
Add Back
</span>
</div>
</div>
</div>
For more info about it
Use ng-class instead. Here's an example of changing background colors with classes:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.portlet = {
classes: {
"parent-portlet": true,
"edit-portlet": false,
"removed": false
}
}
$scope.removePortlet = function(portlet) {
portlet.classes.removed = true;
portlet.classes["edit-portlet"] = true;
};
$scope.addPortlet = function(portlet) {
portlet.classes.removed = false;
portlet.classes["edit-portlet"] = false;
};
});
/* Put your css in here */
.parent-portlet {
background-color: #ccc;
padding: 20px;
}
.parent-portlet.removed {
background-color: #c00;
}
.parent-portlet button {
padding: 10px;
margin: 0 10px;
}
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<script data-require="angular.js#1.5.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.11/angular.min.js" data-semver="1.5.11"></script>
</head>
<body ng-controller="MainCtrl">
<div ng-class="portlet.classes">
<div class="portlet-titlebar">
<button class="remove" ng-click="removePortlet(portlet)">
Remove
</button>
<button class="add-back" ng-click="addPortlet(portlet)">
Add Back
</button>
</div>
</div>
</body>
</html>
I have an observableArray for insert message. I want to display all messages using knockout. I want to use a custom scrollbar graphic - jScrollPane. (plugin LINK)
How can I fix my example for display custom scrollbar from jScrollPane?
Example: http://jsfiddle.net/aZpgY/3/
HTML:
<h2>Chat with knockout binding</h2>
<div id="chat-content" data-bind="foreach: messages">
<div data-bind="text: messageText"></div>
</div>
<br />
<form data-bind="submit: sendMessage">
message: <input data-bind="value: message" placeholder="Insert your massage" /><br />
<button type="submit">Add</button>
</form>
<h2>Example content - without knockout binding</h2>
<div id="example-content">
<div>Text</div>
<div>Text</div>
<div>Text</div>
<div>Text</div>
<div>Text</div>
<div>Text</div>
<div>Text</div>
<div>Text</div>
</div>
CSS:
#chat-content, #example-content{
width: 300px;
height: 100px;
overflow: auto;
}
JS:
function Message(data) {
this.messageText = ko.observable(data.messageText);
}
function ChatViewModel() {
// Data
var self = this;
self.messages = ko.observableArray([]);
self.message = ko.observable();
// Operations
self.sendMessage = function() {
self.messages.push(new Message({ messageText: this.message() }));
self.message("");
};
self.removeTask = function(task) { self.tasks.remove(task) };
}
ko.applyBindings(new ChatViewModel());
$(function(){
$('#chat-content').jScrollPane();
$('#example-content').jScrollPane();
});
Create a custom binding handler to initialize and update the jScrollPane instance:
ko.bindingHandlers.jScrollPane = {
init: function(element, valueAccessor) {
var o = valueAccessor() || {};
// initialize
$(element).jScrollPane(o.options);
var reinit = function() {
var scroll = $(element).data("jsp");
if (scroll) {
scroll.reinitialise();
}
};
// handle window resize (though not really necessary if your chat box has a set pixel width)
$(window).resize(reinit);
// add subscription to observable if passed in
if(o.subscribe) {
o.subscribe.subscribe(function() {
// use setTimeout so the DOM finishes updating before reinitialising
setTimeout(reinit, 0);
});
}
}
};
Call the new jScrollPane handler on the #chat-content div, passing in the messages observable so it knows when to refresh the scroll bar. Put the foreach binding handler in a child element to prevent it from interfering with the DOM changes that jScrollPane makes.
<div id="chat-content" data-bind="jScrollPane: { subscribe: messages }">
<div data-bind="foreach: messages">
<div data-bind="text: messageText"></div>
</div>
</div>
JSFiddle: http://jsfiddle.net/aZpgY/7/
jScrollPane binding handler adapted from here: http://jsfiddle.net/rniemeyer/NgNvf/
In html I am having the following tags:
<span id=M26>2011-2012</span>
<div id=c26 STYLE="display:none">
<span id=M27>2012-2013</span>
<div id=c26 STYLE="display:none">
On Clicking on 2011-2012 or on 2012-2013 I want to set display property of div tag.
I am using the following Javascript code for this and I am calling the Javascript function in body tag. The output is showing style and display is not an object or property.
<script language="javascript">
function clickHnadler()
{
var xid= document.getElementsByTagName("span");
var xsp= xid[0].id;
alert("Span id is "+xsp);
if(xsp.charAt(0)=="M")
{
var oC = document.all("C"& xsp.substring(1,2));
if(oC.STYLE.display == "none")
{
oC.Style.Display = "";
}
else{
oC.Style.Display = "none";
}
}
}
</script>
use jquery:
you can pass in the function the element or the Id:
ex:
<span id=M26>2011-2012</span>
function clickHnadler(element)
{
var id = $(element > span).attr(id);
id[0] = 'c'; //not the nicest way, maybe use a replace or something like that
$(id).show(); //or $(id).css('display','list');
}
You may use clickHandler has following way,
function clickHandler(e) {
window.document.links[0].handleEvent(e);
}
You need to bind event spacifically to elements you want to handle click for. for more information please refer following link,
http://docs.oracle.com/cd/E19957-01/816-6409-10/evnt.htm#1009606
Based on what i understand from your question, I come up with this.
<script type="text/javascript" src="jquery1.8.js"></script>
<span id=M26>2011-2012</span>
<div id=c26 STYLE="display:none">
2011-2012 details</div>
<br />
<span id=M27>2012-2013</span>
<div id=c26 STYLE="display:none">
2012-2013 details
</div>
Given the following HTML:
<div class="component">
<div class="component">
<div class="component">
</div>
</div>
<div class="component">
<div class="somethingelse">
</div>
<div class="component">
</div>
<div class="component">
<input type="button" value="Get Path" onclick="showPath(this)" />
</div>
</div>
</div>
I'm trying to write the function showPath so that it returns the index of the parent div in relation to its siblings of class component. So in the above sample, I would like the function to return 1.
I've got this far, but it returns 2; I don't know what to do to ignore the div of class somethingelse
function showPath(element) {
var component = $(element).closest('.component');
alert(component.index());
}
A quick and simple extension for jQ to turn this process into a method:
$.fn.getIndex = function(){
var index = $(this).parent().children().index( $(this) );
return index;
}
Run this on document.ready or wrap it in a function and run it that way (probably cleaner).
Usage is as simple as
var index_for_element = $('.thing-you-want-index-for').getIndex();
Try this(haven't tested):
function showPath(element) {
var component = $(element).closest('.component');
alert(component.parent().find(".component").index(component));
}
You can do this.
$('input').click(function() {
var component = $(this).closest('.component');
alert(component.parent().children(".component").index(component));
})
Check working example at http://jsfiddle.net/Qzk6A/2/