This code work perfectly. but the suggested text can't control using keyboard
when arrow key up and down. i want to control this suggested text using keyboard
how can i do this. please help..................
/*
*
* jQuery MultiComplete
* =====================
* Written by Tom Hallam
* http://tomhallam.github.com/jQuery-Multicomplete/
* Licenced with the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) licence
* See: http://creativecommons.org/licenses/by-sa/3.0/
*
*/
(function ($) {
$.fn.multicomplete = function (options) {
// Set up the default options
var defaults = {
// Debug mode provides verbose error messages
debug: true,
// Source
source: [],
// AJAX Method (if source is a URL)
method: 'POST',
// Minimum length before a search can be triggered
minimum_length: 3,
// Delay before performing a search, ignored if source is local
search_delay: 500,
// Case sensitive search?
case_sensitive: false,
// Highlight found words?
highlight_results: true,
// Left offset for results panel
offset_left: 0,
// Top offset for results panel
offset_top: 5,
// Result template
result_template: function(row) {
// -- Please fill this in!
},
// Events -------
// On result click
result_click: null,
// On form submit
form_submit: null
},
// Extend the base object
settings = $.extend(defaults, options);
// Object to keep track of our timers
var timers = [],
// And our result groups
groups = {},
// The results themselves
results = [],
// And the query
query = '';
// Iterate over the selected elements and apply the behavior.
return this.each(function () {
multicomplete_init($(this));
});
// Bootstrapper function to attach events to the elements selected
function multicomplete_init(el) {
// Create a unique ID for this element
id = 'multicomplete-' + Math.floor(Math.random() * 1000);
$(el).data('multicomplete-id', id);
// Make a new key in our timer object
timers[id] = {};
// We need to set a timer for input to trigger based on a delay
$(el).on('keyup', function() {
// Keep a local copy of the value
query = $(this).val();
// Clear any old timers
window.clearTimeout(timers[id]);
// If there's nothing left in the input box, do nothing and hide my result panel
if(query.length == 0) {
$('.panel-multicomplete-results.' + id).hide();
return;
}
// Reset the results array
results = [];
// Make sure the query is hitting the minimum length constraint
if(query.length > settings.minimum_length) {
// Where are we sending this search?
switch(typeof(settings.source)) {
case 'string':
timers[id] = window.setTimeout(function(){
multicomplete_searchajax(function() {
multicomplete_render(el);
});
}, settings.search_delay);
break;
case 'object':
multicomplete_searchobject();
multicomplete_render(el);
break;
}
}
}).attr('autocomplete', 'off');
// Hide the DIV when someone clicks outside of the result pane.
$(document).on('mouseup', function(e) {
if($('.panel-multicomplete-results.' + id).has(e.target).length === 0) {
$('.panel-multicomplete-results.' + id).hide();
}
});
}
// Parse a result group
function multicomplete_parsegroup(group_results, group_name) {
// Loop through the group
$(group_results).each(function(index, row) {
for(var field in row) {
// No numbers (for now)
if(typeof row[field] == 'number') {
return true;
}
if(typeof row[field] == 'object') {
multicomplete_parsegroup(row);
}
else {
// If we find a result then push into our results array.
if(multicomplete_match(row[field])) {
results.push({
'field': field,
'row': row,
'group': group_name
});
return true;
}
}
}
});
}
// Does this string match the query
function multicomplete_match(field) {
if(settings.case_sensitive == true) {
return field.indexOf(query) > -1;
}
else {
return field.toLowerCase().indexOf(query.toLowerCase()) > -1;
}
}
// Search an object
function multicomplete_searchobject() {
if(settings.source.length == 0) {
if(settings.debug == true) {
alert('Source was set to an array, but the array was empty.');
}
}
// Loop through the source
for(var group_name in settings.source) {
if(settings.source[group_name].length)
groups[group_name] = multicomplete_parsegroup(settings.source[group_name], group_name);
}
}
// Search an AJAX endpoint
function multicomplete_searchajax(callback) {
// Perform the remote call.
ajax = $.ajax({
'type': settings.method,
'url': settings.source,
'dataType': 'json',
'data': {
'query': query
},
'success': function(data) {
// Loop through the source
for(var group_name in data) {
if(data[group_name].length)
groups[group_name] = multicomplete_parsegroup(data[group_name], group_name);
}
// Call the callback
callback.call(this, data);
},
'error': function(error) {
if(settings.debug == true) {
if(error.status == 412) {
alert('Your remote data source is not valid JSON! Remember to use double quotes instead of single.');
}
if(error.status == 404) {
alert('Your remote data source does not exist on this server.');
}
if(error.status == 500) {
alert('The remote server encountered an error whilst processing your source.');
}
}
}
});
}
// Render a search result
function multicomplete_render(el) {
// Where is the element
l = el.offset().left,
t = el.offset().top,
mc_html_class = 'panel-multicomplete-results ' + el.data('multicomplete-id'),
mc_class = '.panel-multicomplete-results.' + el.data('multicomplete-id');
// Is there already a results div for this element?
if($(mc_class).length == 0) {
// Build the div
$('<div class="' + mc_html_class + '"></div>').css({
'position': 'absolute',
'left': (l + settings.offset_left),
'top': (t + $(el).height() + settings.offset_top)
}).appendTo('body');
}
else {
$(mc_class).empty().show();
}
// Were there any results?
if(results.length == 0 && !$(mc_class + ' .panel-no-results').length) {
$('<div class="panel-no-results">No results found</div>').appendTo(mc_class);
}
else {
// Create a results div
$('<div class="results"></div>').appendTo(mc_class);
// Loop through the results and group them again
$(results).each(function(index, result) {
if($(mc_class + ' .results .' + result.group).length == 0) {
$('<div class="group ' + result.group + '"><div class="group-title">' + result.group + '</div><div class="group-items"></div></div>').appendTo(mc_class + ' .results');
}
// Cache the result row
r = $('<div class="result"></div>').appendTo(mc_class + ' .results .' + result.group + ' .group-items');
// Get the HTML for the result template
result_tmpl = settings.result_template.call(this, result.row, result.group, result.field);
// Apply the click action
$(result_tmpl).on('click', function() {
if(typeof settings.result_click == 'function') {
settings.result_click.call(this, result.row, result.group);
}
else {
multicomplete_defaultclick(result.row, result.group, el);
}
}).appendTo(r);
});
// Apply a clearfix to the groups
$('<div class="clearfix"></div>').appendTo(mc_class + ' .results .group');
// If we have the highlight option turned on then do that
if(settings.highlight_results == true) {
multicomplete_highlight($(mc_class + ' .results').get(0), query.toUpperCase());
}
}
}
// Default click action for a result
function multicomplete_defaultclick(result, group, el) {
// Is there even a form?
if($(el).closest('form').length == 0) {
}
else {
// Override the form submit to do some funky tings
$(el).closest('form').on('submit', function(e) {
// Check if we've already modified the form
if($(this).data('multicomplete-modified') == true) {
$(this).submit();
}
else {
// Stop the form from submitting
e.preventDefault();
// Modify the element
if(!!el.attr('name')) {
old_name = el.attr('name');
el.attr('name', el.attr('name' + '-mc-dummy'));
}
// Create a new hidden element with the ID
$('<input type="hidden" name="' + old_name + '" value="' + (!!result.id ? result.id : JSON.stringify(result)) + '" />').insertAfter(el);
// Add the checkpoint on to the form
$(this).data('multicomplete-modified', true);
// Submit the form
$(this).submit();
}
});
}
}
/*
highlight v3
Highlights arbitrary terms.
<http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html>
MIT license.
Johann Burkard
<http://johannburkard.de>
<mailto:jb#eaio.com>
*/
function multicomplete_highlight(node, pat) {
var skip = 0;
if (node.nodeType == 3) {
var pos = node.data.toUpperCase().indexOf(pat);
if (pos >= 0) {
var spannode = document.createElement('span');
spannode.className = 'highlight';
var middlebit = node.splitText(pos);
var endbit = middlebit.splitText(pat.length);
var middleclone = middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode, middlebit);
skip = 1;
}
} else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
for (var i = 0; i < node.childNodes.length; ++i) {
i += multicomplete_highlight(node.childNodes[i], pat);
}
}
return skip;
}
}
})(jQuery);
$(document).ready(function() {
$('#input-multicomplete').multicomplete({
minimum_length: 1,
result_template: function(result, group, matched_field) {
tmpl = '<div>';
if(!!result.image) {
tmpl += '<div class="image"><img src="' + result.image + '" /></div>';
}
tmpl += '<div>' + result.name + '</div>';
if(!!result.address) {
tmpl += '<div class="meta">' + result.address + '</div>';
}
// Only display this field if something was matched in it
if(!!result.cuisine && matched_field == 'cuisine') {
tmpl += '<div class="cuisine">Cuisine offered: ' + result.cuisine + '</div>';
}
tmpl += '</div>';
return tmpl;
},
result_click: function(row, group) {
alert('You chose "' + row.name + '" in ' + group);
},
source: {
"Attractions": [
{
"name": "The Tower of London",
"address": "London, EC3N 4AB",
"image": "http://www.hrp.org.uk/Images/TOL_Main.jpg"
},
{
"name": "Camden Lock Market",
"address": "1 Kentish Town Road, London, NW1 8",
"image": "http://www.london-attractions.info/images/attractions/camden-market.jpg"
},
{
"name": "Anne Frank Museum",
"address": "Prinsengracht 267, 1000 AS, Amsterdam",
"image": "http://upload.wikimedia.org/wikipedia/commons/thumb/9/9c/AnneFrankHouseAmsterdamtheNetherlands.jpg/220px-AnneFrankHouseAmsterdamtheNetherlands.jpg"
}
],
"Hotels": [
{
"name": "The Ritz",
"address": "150 Piccadilly, London, W1J 9BR",
"image": "http://www.londonhotels.net/images/photogallery/the-ritz-london/the-ritz-london.jpg"
},
{
"name": "51 Buckingham Gate",
"address": "51 Buckingham Gate, London, SW1E 6AF",
"image": "http://static.laterooms.com/hotelphotos/laterooms/193559/gallery/51-buckingham-gate-london_060620111405093617.jpg"
},
{
"name": "Hotel de l'Europe",
"address": "2–14 Nieuwe Doelenstraat, Amsterdam, 1012 CP ",
"image": "http://www.concierge.com/images/cnt/lists/goldlist06/europe/netherlands/amsterdam/hotel_de_leurope/amsterdam_hotel_002p.jpg"
}
],
"Restaurant": [
{
"name": "Petrus",
"address": "1 Kinnerton Street, Knightsbridge, London, SW1X 8EA",
"image": "http://berkshirereview.net/images/petrus_london_dining.jpg"
},
{
"name": "Vermeer",
"address": "Prins Hendrikkade 59-72, 1012 AD Amsterdam ",
"image": "http://www.restaurantvermeer.nl/Portals/7/UltraPhotoGallery/3425/45/[7].Vermeer---desert-2.jpg"
}
]
}
});
});
/* DEMO STYLES */
.result .image {
float: left;
margin-right: 10px;
}
.result .image img {
width: 32px;
height: 32px;
border: 1px solid #ccc;
padding: 1px;
}
.result .meta {
font-size: 11px;
color: #666;
}
.result a {
text-decoration: underline;
}
.result:hover {
background-color: #f7f7f7;
}
/*
*
* jQuery MultiComplete
* =====================
* Written by Tom Hallam
* http://tomhallam.github.com/jQuery-Multicomplete/
* Licenced with the Creative Commons Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) licence
* See: http://creativecommons.org/licenses/by-sa/3.0/
*
*/
.panel-multicomplete-results {
border: 1px solid #ccc;
width: 420px;
font-family: Tahoma;
font-size: 12px;
background: url(mc-bg.png) repeat-y;
}
.panel-multicomplete-results .result {
padding: 5px;
border-bottom: 1px solid #e7e7e7;
cursor: pointer;
}
.panel-multicomplete-results .result:last-child {
border: none;
}
.panel-multicomplete-results .group {
border-bottom: 1px solid #ccc;
}
.panel-multicomplete-results .group:last-child {
border: none;
}
.panel-multicomplete-results .group-title {
float: left;
width: 100px;
padding: 5px;
font-weight: bold;
}
.panel-multicomplete-results .group-items {
float: left;
width: 300px;
}
.highlight {
font-weight: bold;
}
/* UTILITIES */
.clearfix {
clear: both;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
Start typing a city: <input type="text" name="multiselect" id="input-multicomplete" />
</div>
https://jsfiddle.net/ynyqed1m/
Related
I've got a multi select dropdown that displays a selection of countries. I want to have some of these preselected based on the content of an array.
Based on a similar question here How can I check checkboxes based on values? I tried using
var arrayValues = (246,247,248,249,250,251,252,253,254,255,256,257,258,259,261,262,263,265,266,267,268,270,271,272,273,274,275);
var i = 0;
while (arrayValues.length < i) {
var val = arrayValues[i];
$('#restrictCountry input[value="' + val + '"]').prop('checked', 'checked');
i++;
}
but it isn't pre selecting the checkboxes with the values shown in the array.
I've set up a fiddle so you can see how my multi select dropdown works. The pre select script is at the bottom of the javascript pane.
What have I done wrong here?
First you'are mistaken in the array syntax ,
also the loop condition is also falsy ,
and finnaly the selector you made couldn't reach newly created multi select wrapper ,
What I suggest ( a bit tricky ) is to rectify selector , then trigger a click on the check input foreach value ,( this will check the select hidden and genrated wrapper input same time )
while (i < arrayValues.length) {
var val = arrayValues[i];
$('#restrictCountry').next(".ms-options-wrap").find(` input[value=${val}]`).not(":checked").click();
i++;
}
check below snippet :
(function($) {
var defaults = {
placeholder: 'Select options', // text to use in dummy input
columns: 1, // how many columns should be use to show options
search: false, // include option search box
// search filter options
searchOptions: {
'default': 'Search', // search input placeholder text
showOptGroups: false, // show option group titles if no options remaining
onSearch: function(element) {} // fires on keyup before search on options happens
},
selectAll: false, // add select all option
selectGroup: false, // select entire optgroup
minHeight: 200, // minimum height of option overlay
maxHeight: null, // maximum height of option overlay
showCheckbox: true, // display the checkbox to the user
jqActualOpts: {}, // options for jquery.actual
// Callbacks
onLoad: function(element) { // fires at end of list initialization
$(element).hide();
},
onOptionClick: function(element, option) {}, // fires when an option is clicked
// #NOTE: these are for future development
maxWidth: null, // maximum width of option overlay (or selector)
minSelect: false, // minimum number of items that can be selected
maxSelect: false, // maximum number of items that can be selected
};
var msCounter = 1;
function MultiSelect(element, options) {
this.element = element;
this.options = $.extend({}, defaults, options);
this.load();
}
MultiSelect.prototype = {
/* LOAD CUSTOM MULTISELECT DOM/ACTIONS */
load: function() {
var instance = this;
// make sure this is a select list and not loaded
if ((instance.element.nodeName != 'SELECT') || $(instance.element).hasClass('jqmsLoaded')) {
return true;
}
// sanity check so we don't double load on a select element
$(instance.element).addClass('jqmsLoaded');
// add option container
$(instance.element).after('<div class="ms-options-wrap"><button>None Selected</button><div class="ms-options"><ul></ul></div></div>');
var placeholder = $(instance.element).next('.ms-options-wrap').find('> button:first-child');
var optionsWrap = $(instance.element).next('.ms-options-wrap').find('> .ms-options');
var optionsList = optionsWrap.find('> ul');
var hasOptGroup = $(instance.element).find('optgroup').length ? true : false;
var maxWidth = null;
if (typeof instance.options.width == 'number') {
optionsWrap.parent().css('position', 'relative');
maxWidth = instance.options.width;
} else if (typeof instance.options.width == 'string') {
$(instance.options.width).css('position', 'relative');
maxWidth = '100%';
} else {
optionsWrap.parent().css('position', 'relative');
}
var maxHeight = ($(window).height() - optionsWrap.offset().top - 20);
if (instance.options.maxHeight) {
maxHeight = ($(window).height() - optionsWrap.offset().top - 20);
maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxheight;
}
maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxHeight;
optionsWrap.css({
maxWidth: maxWidth,
minHeight: instance.options.minHeight,
maxHeight: maxHeight,
overflow: 'auto'
}).hide();
// isolate options scroll
// #source: https://github.com/nobleclem/jQuery-IsolatedScroll
optionsWrap.bind('touchmove mousewheel DOMMouseScroll', function(e) {
if (($(this).outerHeight() < $(this)[0].scrollHeight)) {
var e0 = e.originalEvent,
delta = e0.wheelDelta || -e0.detail;
if (($(this).outerHeight() + $(this)[0].scrollTop) > $(this)[0].scrollHeight) {
e.preventDefault();
this.scrollTop += (delta < 0 ? 1 : -1);
}
}
});
// hide options menus if click happens off of the list placeholder button
$(document).off('click.ms-hideopts').on('click.ms-hideopts', function(event) {
if (!$(event.target).closest('.ms-options-wrap').length) {
$('.ms-options-wrap > .ms-options:visible').hide();
}
});
// disable button action
placeholder.bind('mousedown', function(event) {
// ignore if its not a left click
if (event.which != 1) {
return true;
}
// hide other menus before showing this one
$('.ms-options-wrap > .ms-options:visible').each(function() {
if ($(this).parent().prev()[0] != optionsWrap.parent().prev()[0]) {
$(this).hide();
}
});
// show/hide options
optionsWrap.toggle();
// recalculate height
if (optionsWrap.is(':visible')) {
optionsWrap.css('maxHeight', '');
var maxHeight = ($(window).height() - optionsWrap.offset().top - 20);
if (instance.options.maxHeight) {
maxHeight = ($(window).height() - optionsWrap.offset().top - 20);
maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxheight;
}
maxHeight = maxHeight < instance.options.minHeight ? instance.options.minHeight : maxHeight;
optionsWrap.css('maxHeight', maxHeight);
}
}).click(function(event) {
event.preventDefault();
});
// add placeholder copy
if (instance.options.placeholder) {
placeholder.text(instance.options.placeholder);
}
// add search box
if (instance.options.search) {
optionsList.before('<div class="ms-search"><input type="text" value="" placeholder="' + instance.options.searchOptions['default'] + '" /></div>');
var search = optionsWrap.find('.ms-search input');
search.on('keyup', function() {
// ignore keystrokes that don't make a difference
if ($(this).data('lastsearch') == $(this).val()) {
return true;
}
$(this).data('lastsearch', $(this).val());
// USER CALLBACK
if (typeof instance.options.searchOptions.onSearch == 'function') {
instance.options.searchOptions.onSearch(instance.element);
}
// search non optgroup li's
optionsList.find('li:not(.optgroup)').each(function() {
var optText = $(this).text();
// show option if string exists
if (optText.toLowerCase().indexOf(search.val().toLowerCase()) > -1) {
$(this).show();
}
// don't hide selected items
else if (!$(this).hasClass('selected')) {
$(this).hide();
}
// hide / show optgroups depending on if options within it are visible
if (!instance.options.searchOptions.showOptGroups && $(this).closest('li.optgroup')) {
$(this).closest('li.optgroup').show();
if ($(this).closest('li.optgroup').find('li:visible').length) {
$(this).closest('li.optgroup').show();
} else {
$(this).closest('li.optgroup').hide();
}
}
});
});
}
// add global select all options
if (instance.options.selectAll) {
optionsList.before('Select all');
}
// handle select all option
optionsWrap.on('click', '.ms-selectall', function(event) {
event.preventDefault();
if ($(this).hasClass('global')) {
// check if any selected if so then select them
if (optionsList.find('li:not(.optgroup)').filter(':not(.selected)').length) {
optionsList.find('li:not(.optgroup)').filter(':not(.selected)').find('input[type="checkbox"]').trigger('click');
}
// deselect everything
else {
optionsList.find('li:not(.optgroup).selected input[type="checkbox"]').trigger('click');
}
} else if ($(this).closest('li').hasClass('optgroup')) {
var optgroup = $(this).closest('li.optgroup');
// check if any selected if so then select them
if (optgroup.find('li:not(.selected)').length) {
optgroup.find('li:not(.selected) input[type="checkbox"]').trigger('click');
}
// deselect everything
else {
optgroup.find('li.selected input[type="checkbox"]').trigger('click');
}
}
});
// add options to wrapper
var options = [];
$(instance.element).children().each(function() {
if (this.nodeName == 'OPTGROUP') {
var groupOptions = [];
$(this).children('option').each(function() {
groupOptions[$(this).val()] = {
name: $(this).text(),
value: $(this).val(),
checked: $(this).prop('selected')
};
});
options.push({
label: $(this).attr('label'),
options: groupOptions
});
} else if (this.nodeName == 'OPTION') {
options.push({
name: $(this).text(),
value: $(this).val(),
checked: $(this).prop('selected')
});
} else {
// bad option
return true;
}
});
instance.loadOptions(options);
// COLUMNIZE
if (hasOptGroup) {
// float non grouped options
optionsList.find('> li:not(.optgroup)').css({
float: 'left',
width: (100 / instance.options.columns) + '%'
});
// add CSS3 column styles
optionsList.find('li.optgroup').css({
clear: 'both'
}).find('> ul').css({
'column-count': instance.options.columns,
'column-gap': 0,
'-webkit-column-count': instance.options.columns,
'-webkit-column-gap': 0,
'-moz-column-count': instance.options.columns,
'-moz-column-gap': 0
});
// for crappy IE versions float grouped options
if (this._ieVersion() && (this._ieVersion() < 10)) {
optionsList.find('li.optgroup > ul > li').css({
float: 'left',
width: (100 / instance.options.columns) + '%'
});
}
} else {
// add CSS3 column styles
optionsList.css({
'column-count': instance.options.columns,
'column-gap': 0,
'-webkit-column-count': instance.options.columns,
'-webkit-column-gap': 0,
'-moz-column-count': instance.options.columns,
'-moz-column-gap': 0
});
// for crappy IE versions float grouped options
if (this._ieVersion() && (this._ieVersion() < 10)) {
optionsList.find('> li').css({
float: 'left',
width: (100 / instance.options.columns) + '%'
});
}
}
// BIND SELECT ACTION
optionsWrap.on('click', 'input[type="checkbox"]', function() {
$(this).closest('li').toggleClass('selected');
var select = optionsWrap.parent().prev();
// toggle clicked option
select.find('option[value="' + $(this).val() + '"]').prop(
'selected', $(this).is(':checked')
).closest('select').trigger('change');
if (typeof instance.options.onOptionClick == 'function') {
instance.options.onOptionClick();
}
instance._updatePlaceholderText();
});
// hide native select list
if (typeof instance.options.onLoad === 'function') {
instance.options.onLoad(instance.element);
} else {
$(instance.element).hide();
}
},
/* LOAD SELECT OPTIONS */
loadOptions: function(options, overwrite) {
overwrite = (typeof overwrite == 'boolean') ? overwrite : true;
var instance = this;
var optionsList = $(instance.element).next('.ms-options-wrap').find('> .ms-options > ul');
if (overwrite) {
optionsList.find('> li').remove();
}
for (var key in options) {
var thisOption = options[key];
var container = $('<li></li>');
// optgroup
if (thisOption.hasOwnProperty('options')) {
container.addClass('optgroup');
container.append('<span class="label">' + thisOption.label + '</span>');
container.find('> .label').css({
clear: 'both'
});
if (instance.options.selectGroup) {
container.append('Select all')
}
container.append('<ul></ul>');
for (var gKey in thisOption.options) {
var thisGOption = thisOption.options[gKey];
var gContainer = $('<li></li>').addClass('ms-reflow');
instance._addOption(gContainer, thisGOption);
container.find('> ul').append(gContainer);
}
}
// option
else if (thisOption.hasOwnProperty('value')) {
container.addClass('ms-reflow')
instance._addOption(container, thisOption);
}
optionsList.append(container);
}
optionsList.find('.ms-reflow input[type="checkbox"]').each(function(idx) {
if ($(this).css('display').match(/block$/)) {
var checkboxWidth = $(this).outerWidth();
checkboxWidth = checkboxWidth ? checkboxWidth : 15;
$(this).closest('label').css(
'padding-left',
(parseInt($(this).closest('label').css('padding-left')) * 2) + checkboxWidth
);
$(this).closest('.ms-reflow').removeClass('ms-reflow');
}
});
instance._updatePlaceholderText();
},
/* RESET THE DOM */
unload: function() {
$(this.element).next('.ms-options-wrap').remove();
$(this.element).show(function() {
$(this).css('display', '').removeClass('jqmsLoaded');
});
},
/* RELOAD JQ MULTISELECT LIST */
reload: function() {
// remove existing options
$(this.element).next('.ms-options-wrap').remove();
$(this.element).removeClass('jqmsLoaded');
// load element
this.load();
},
/** PRIVATE FUNCTIONS **/
// update selected placeholder text
_updatePlaceholderText: function() {
var instance = this;
var placeholder = $(instance.element).next('.ms-options-wrap').find('> button:first-child');
var optionsWrap = $(instance.element).next('.ms-options-wrap').find('> .ms-options');
var select = optionsWrap.parent().prev();
// get selected options
var selOpts = [];
select.find('option:selected').each(function() {
selOpts.push($(this).text());
});
// UPDATE PLACEHOLDER TEXT WITH OPTIONS SELECTED
placeholder.text(selOpts.join(', '));
var copy = placeholder.clone().css({
display: 'inline',
width: 'auto',
visibility: 'hidden'
}).appendTo(optionsWrap.parent());
// if the jquery.actual plugin is loaded use it to get the widths
var copyWidth = (typeof $.fn.actual !== 'undefined') ? copy.actual('width', instance.options.jqActualOpts) : copy.width();
var placeWidth = (typeof $.fn.actual !== 'undefined') ? placeholder.actual('width', instance.options.jqActualOpts) : placeholder.width();
// if copy is larger than button width use "# selected"
if (copyWidth > placeWidth) {
placeholder.text(selOpts.length + ' selected');
}
// if options selected then use those
else if (selOpts.length) {
placeholder.text(selOpts.join(', '));
}
// replace placeholder text
else {
placeholder.text(instance.options.placeholder);
}
// remove dummy element
copy.remove();
},
// Add option to the custom dom list
_addOption: function(container, option) {
container.text(option.name);
container.prepend(
$('<input type="checkbox" value="" title="" />')
.val(option.value)
.attr('title', option.name)
.attr('id', 'ms-opt-' + msCounter)
);
if (option.checked) {
container.addClass('default');
container.addClass('selected');
container.find('input[type="checkbox"]').prop('checked', true);
}
var label = $('<label></label>').attr('for', 'ms-opt-' + msCounter);
container.wrapInner(label);
if (!this.options.showCheckbox) {
container.find('input[id="ms-opt-' + msCounter + '"]').hide();
}
msCounter = msCounter + 1;
},
// check ie version
_ieVersion: function() {
var myNav = navigator.userAgent.toLowerCase();
return (myNav.indexOf('msie') != -1) ? parseInt(myNav.split('msie')[1]) : false;
}
};
// ENABLE JQUERY PLUGIN FUNCTION
$.fn.multiselect = function(options) {
var args = arguments;
var ret;
// menuize each list
if ((options === undefined) || (typeof options === 'object')) {
return this.each(function() {
if (!$.data(this, 'plugin_multiselect')) {
$.data(this, 'plugin_multiselect', new MultiSelect(this, options));
}
});
} else if ((typeof options === 'string') && (options[0] !== '_') && (options !== 'init')) {
this.each(function() {
var instance = $.data(this, 'plugin_multiselect');
if (instance instanceof MultiSelect && typeof instance[options] === 'function') {
ret = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
}
// special destruct handler
if (options === 'unload') {
$.data(this, 'plugin_multiselect', null);
}
});
return ret;
}
};
}(jQuery));
$('#restrictCountry').multiselect({
columns: 4,
placeholder: 'Select Restricted Countries',
search: true,
selectAll: true
});
$(function() {
var arrayValues = [246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 261, 262, 263, 265, 266, 267, 268, 270, 271, 272, 273, 274, 275];
var i = 0;
while (i < arrayValues.length) {
var val = arrayValues[i];
$('#restrictCountry').next(".ms-options-wrap").find(` input[value=${val}]`).not(":checked").click();
i++;
}
})
.ms-options-wrap,
.ms-options-wrap * {
box-sizing: border-box;
list-style-type: none;
}
.ms-options-wrap>button:focus,
.ms-options-wrap>button {
position: relative;
width: 100%;
text-align: left;
border: 1px solid #aaa;
background-color: #fff;
padding: 5px 20px 5px 5px;
margin-top: 1px;
font-size: 13px;
color: #aaa;
outline: none;
white-space: nowrap;
}
.ms-options-wrap>button:after {
content: ' ';
height: 0;
position: absolute;
top: 50%;
right: 5px;
width: 0;
border: 6px solid rgba(0, 0, 0, 0);
border-top-color: #999;
margin-top: -3px;
}
.ms-options-wrap>.ms-options {
position: absolute;
left: 0;
width: 100%;
margin-top: 1px;
margin-bottom: 20px;
background: white;
z-index: 2000;
border: 1px solid #aaa;
text-align: left;
}
.ms-options-wrap>.ms-options>.ms-search input {
width: 100%;
padding: 4px 5px;
border: none;
border-bottom: 1px groove;
outline: none;
}
.ms-options-wrap>.ms-options .ms-selectall {
display: inline-block;
font-size: .9em;
text-transform: lowercase;
text-decoration: none;
}
.ms-options-wrap>.ms-options .ms-selectall:hover {
text-decoration: underline;
}
.ms-options-wrap>.ms-options>.ms-selectall.global {
margin: 4px 5px;
}
.ms-options-wrap>.ms-options>ul>li.optgroup {
padding: 5px;
}
.ms-options-wrap>.ms-options>ul>li.optgroup+li.optgroup {
border-top: 1px solid #aaa;
}
.ms-options-wrap>.ms-options>ul>li.optgroup .label {
display: block;
padding: 5px 0 0 0;
font-weight: bold;
}
.ms-options-wrap>.ms-options>ul label {
position: relative;
display: inline-block;
width: 100%;
padding: 8px 4px;
margin: 1px 0;
}
.ms-options-wrap>.ms-options>ul li.selected label,
.ms-options-wrap>.ms-options>ul label:hover {
background-color: #efefef;
}
.ms-options-wrap>.ms-options>ul input[type="checkbox"] {
margin-right: 5px;
position: absolute;
left: 4px;
top: 7px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="form-group">
<p class="col-sm-3 control-label">Restricted Countries:</p>
<div class="col-sm-9 col-md-6">
<select rel="dropdown" name="restrictCountry[]" multiple id="restrictCountry">
<option value="253">Austria</option>
<option value="252">Belgium</option>
<option value="266">Bulgaria</option>
<option value="270">Croatia</option>
<option value="274">Czech Republic</option>
<option value="254">Denmark</option>
<option value="262">Estonia</option>
<option value="258">Finland</option>
<option value="247">France</option>
<option value="248">Germany</option>
<option value="260">Gibraltar</option>
<option value="265">Greece</option>
<option value="243">Guernsey</option>
<option value="267">Hungary</option>
<option value="264">Iceland</option>
<option value="246">Ireland</option>
<option value="244">Isle of Man</option>
<option value="255">Italy</option>
<option value="245">Jersey</option>
<option value="263">Latvia</option>
<option value="259">Lithuania</option>
<option value="275">Luxembourg</option>
<option value="273">Malta</option>
<option value="242">Montenegro</option>
<option value="249">Netherlands</option>
<option value="268">Norway</option>
<option value="241">Palestine, State of</option>
<option value="250">Poland</option>
<option value="261">Portugal</option>
<option value="272">Romania</option>
<option value="277">Serbia</option>
<option value="271">Slovakia</option>
<option value="256">Slovenia</option>
<option value="251">Spain</option>
<option value="257">Sweden</option>
<option value="269">Switzerland</option>
<option value="276">Turkey</option>
</select>
</div>
</div>
fix your lines:
var arrayValues = [246,247,248,249,250,251,252,253,254,255,256,257,258,259,261,262,263,265,266,267,268,270,271,272,273,274,275];
var i = 0;
while (arrayValues.length > i) {
var val = arrayValues[i];
$('li input[value=' + val + ']').prop('checked', true);
i++;
}
the problem is comming the fact the dropdown is built from the options defined..If you see the picture, you cant access to input from the id of select tag.
The requirement is to sow the information continuously hence opted for a ticker style.
Now I am using an [ticker-style.css] along with [jquery.ticker.js]
It works fine in a Full Screen however while browsing in a Mobile/Tabler - the text is getting cut (see below screenshot) - I tried to play around the width however the rendering was not as expected.
Can you help here.
Thanks in advance.
/*
jQuery News Ticker is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, version 2 of the License.
jQuery News Ticker is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with jQuery News Ticker. If not, see <http://www.gnu.org/licenses/>.
*/
(function($){
$.fn.ticker = function(options) {
// Extend our default options with those provided.
// Note that the first arg to extend is an empty object -
// this is to keep from overriding our "defaults" object.
var opts = $.extend({}, $.fn.ticker.defaults, options);
// check that the passed element is actually in the DOM
if ($(this).length == 0) {
if (window.console && window.console.log) {
window.console.log('Element does not exist in DOM!');
}
else {
alert('Element does not exist in DOM!');
}
return false;
}
/* Get the id of the UL to get our news content from */
var newsID = '#' + $(this).attr('id');
/* Get the tag type - we will check this later to makde sure it is a UL tag */
var tagType = $(this).get(0).tagName;
return this.each(function() {
// get a unique id for this ticker
var uniqID = getUniqID();
/* Internal vars */
var settings = {
position: 0,
time: 0,
distance: 0,
newsArr: {},
play: true,
paused: false,
contentLoaded: false,
dom: {
contentID: '#ticker-content-' + uniqID,
titleID: '#ticker-title-' + uniqID,
titleElem: '#ticker-title-' + uniqID + ' SPAN',
tickerID : '#ticker-' + uniqID,
wrapperID: '#ticker-wrapper-' + uniqID,
revealID: '#ticker-swipe-' + uniqID,
revealElem: '#ticker-swipe-' + uniqID + ' SPAN',
controlsID: '#ticker-controls-' + uniqID,
prevID: '#prev-' + uniqID,
nextID: '#next-' + uniqID,
playPauseID: '#play-pause-' + uniqID
}
};
// if we are not using a UL, display an error message and stop any further execution
if (tagType != 'UL' && tagType != 'OL' && opts.htmlFeed === true) {
debugError('Cannot use <' + tagType.toLowerCase() + '> type of element for this plugin - must of type <ul> or <ol>');
return false;
}
// set the ticker direction
opts.direction == 'rtl' ? opts.direction = 'right' : opts.direction = 'left';
// lets go...
initialisePage();
/* Function to get the size of an Object*/
function countSize(obj) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
function getUniqID() {
var newDate = new Date;
return newDate.getTime();
}
/* Function for handling debug and error messages */
function debugError(obj) {
if (opts.debugMode) {
if (window.console && window.console.log) {
window.console.log(obj);
}
else {
alert(obj);
}
}
}
/* Function to setup the page */
function initialisePage() {
// process the content for this ticker
processContent();
// add our HTML structure for the ticker to the DOM
$(newsID).wrap('<div id="' + settings.dom.wrapperID.replace('#', '') + '"></div>');
// remove any current content inside this ticker
$(settings.dom.wrapperID).children().remove();
$(settings.dom.wrapperID).append('<div id="' + settings.dom.tickerID.replace('#', '') + '" class="ticker"><div id="' + settings.dom.titleID.replace('#', '') + '" class="ticker-title"><span><!-- --></span></div><p id="' + settings.dom.contentID.replace('#', '') + '" class="ticker-content"></p><div id="' + settings.dom.revealID.replace('#', '') + '" class="ticker-swipe"><span><!-- --></span></div></div>');
$(settings.dom.wrapperID).removeClass('no-js').addClass('ticker-wrapper has-js ' + opts.direction);
// hide the ticker
$(settings.dom.tickerElem + ',' + settings.dom.contentID).hide();
// add the controls to the DOM if required
if (opts.controls) {
// add related events - set functions to run on given event
$(settings.dom.controlsID).on('click mouseover mousedown mouseout mouseup', function (e) {
var button = e.target.id;
if (e.type == 'click') {
switch (button) {
case settings.dom.prevID.replace('#', ''):
// show previous item
settings.paused = true;
$(settings.dom.playPauseID).addClass('paused');
manualChangeContent('prev');
break;
case settings.dom.nextID.replace('#', ''):
// show next item
settings.paused = true;
$(settings.dom.playPauseID).addClass('paused');
manualChangeContent('next');
break;
case settings.dom.playPauseID.replace('#', ''):
// play or pause the ticker
if (settings.play == true) {
settings.paused = true;
$(settings.dom.playPauseID).addClass('paused');
pauseTicker();
}
else {
settings.paused = false;
$(settings.dom.playPauseID).removeClass('paused');
restartTicker();
}
break;
}
}
else if (e.type == 'mouseover' && $('#' + button).hasClass('controls')) {
$('#' + button).addClass('over');
}
else if (e.type == 'mousedown' && $('#' + button).hasClass('controls')) {
$('#' + button).addClass('down');
}
else if (e.type == 'mouseup' && $('#' + button).hasClass('controls')) {
$('#' + button).removeClass('down');
}
else if (e.type == 'mouseout' && $('#' + button).hasClass('controls')) {
$('#' + button).removeClass('over');
}
});
// add controls HTML to DOM
$(settings.dom.wrapperID).append('<ul id="' + settings.dom.controlsID.replace('#', '') + '" class="ticker-controls"><li id="' + settings.dom.playPauseID.replace('#', '') + '" class="jnt-play-pause controls"><!-- --></li><li id="' + settings.dom.prevID.replace('#', '') + '" class="jnt-prev controls"><!-- --></li><li id="' + settings.dom.nextID.replace('#', '') + '" class="jnt-next controls"><!-- --></li></ul>');
}
if (opts.displayType != 'fade') {
// add mouse over on the content
$(settings.dom.contentID).mouseover(function () {
if (settings.paused == false) {
pauseTicker();
}
}).mouseout(function () {
if (settings.paused == false) {
restartTicker();
}
});
}
// we may have to wait for the ajax call to finish here
if (!opts.ajaxFeed) {
setupContentAndTriggerDisplay();
}
}
/* Start to process the content for this ticker */
function processContent() {
// check to see if we need to load content
if (settings.contentLoaded == false) {
// construct content
if (opts.ajaxFeed) {
if (opts.feedType == 'xml') {
$.ajax({
url: opts.feedUrl,
cache: false,
dataType: opts.feedType,
async: true,
success: function(data){
count = 0;
// get the 'root' node
for (var a = 0; a < data.childNodes.length; a++) {
if (data.childNodes[a].nodeName == 'rss') {
xmlContent = data.childNodes[a];
}
}
// find the channel node
for (var i = 0; i < xmlContent.childNodes.length; i++) {
if (xmlContent.childNodes[i].nodeName == 'channel') {
xmlChannel = xmlContent.childNodes[i];
}
}
// for each item create a link and add the article title as the link text
for (var x = 0; x < xmlChannel.childNodes.length; x++) {
if (xmlChannel.childNodes[x].nodeName == 'item') {
xmlItems = xmlChannel.childNodes[x];
var title, link = false;
for (var y = 0; y < xmlItems.childNodes.length; y++) {
if (xmlItems.childNodes[y].nodeName == 'title') {
title = xmlItems.childNodes[y].lastChild.nodeValue;
}
else if (xmlItems.childNodes[y].nodeName == 'link') {
link = xmlItems.childNodes[y].lastChild.nodeValue;
}
if ((title !== false && title != '') && link !== false) {
settings.newsArr['item-' + count] = { type: opts.titleText, content: '' + title + '' }; count++; title = false; link = false;
}
}
}
}
// quick check here to see if we actually have any content - log error if not
if (countSize(settings.newsArr < 1)) {
debugError('Couldn\'t find any content from the XML feed for the ticker to use!');
return false;
}
settings.contentLoaded = true;
setupContentAndTriggerDisplay();
}
});
}
else {
debugError('Code Me!');
}
}
else if (opts.htmlFeed) {
if($(newsID + ' LI').length > 0) {
$(newsID + ' LI').each(function (i) {
// maybe this could be one whole object and not an array of objects?
settings.newsArr['item-' + i] = { type: opts.titleText, content: $(this).html()};
});
}
else {
debugError('Couldn\'t find HTML any content for the ticker to use!');
return false;
}
}
else {
debugError('The ticker is set to not use any types of content! Check the settings for the ticker.');
return false;
}
}
}
function setupContentAndTriggerDisplay() {
settings.contentLoaded = true;
// update the ticker content with the correct item
// insert news content into DOM
$(settings.dom.titleElem).html(settings.newsArr['item-' + settings.position].type);
$(settings.dom.contentID).html(settings.newsArr['item-' + settings.position].content);
// set the next content item to be used - loop round if we are at the end of the content
if (settings.position == (countSize(settings.newsArr) -1)) {
settings.position = 0;
}
else {
settings.position++;
}
// get the values of content and set the time of the reveal (so all reveals have the same speed regardless of content size)
distance = $(settings.dom.contentID).width();
time = distance / opts.speed;
// start the ticker animation
revealContent();
}
// slide back cover or fade in content
function revealContent() {
$(settings.dom.contentID).css('opacity', '1');
if(settings.play) {
// get the width of the title element to offset the content and reveal
var offset = $(settings.dom.titleID).width() + 20;
$(settings.dom.revealID).css(opts.direction, offset + 'px');
// show the reveal element and start the animation
if (opts.displayType == 'fade') {
// fade in effect ticker
$(settings.dom.revealID).hide(0, function () {
$(settings.dom.contentID).css(opts.direction, offset + 'px').fadeIn(opts.fadeInSpeed, postReveal);
});
}
else if (opts.displayType == 'scroll') {
// to code
}
else {
// default bbc scroll effect
$(settings.dom.revealElem).show(0, function () {
$(settings.dom.contentID).css(opts.direction, offset + 'px').show();
// set our animation direction
animationAction = opts.direction == 'right' ? { marginRight: distance + 'px'} : { marginLeft: distance + 'px' };
$(settings.dom.revealID).css('margin-' + opts.direction, '0px').delay(20).animate(animationAction, time, 'linear', postReveal);
});
}
}
else {
return false;
}
};
// here we hide the current content and reset the ticker elements to a default state ready for the next ticker item
function postReveal() {
if(settings.play) {
// we have to separately fade the content out here to get around an IE bug - needs further investigation
$(settings.dom.contentID).delay(opts.pauseOnItems).fadeOut(opts.fadeOutSpeed);
// deal with the rest of the content, prepare the DOM and trigger the next ticker
if (opts.displayType == 'fade') {
$(settings.dom.contentID).fadeOut(opts.fadeOutSpeed, function () {
$(settings.dom.wrapperID)
.find(settings.dom.revealElem + ',' + settings.dom.contentID)
.hide()
.end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
.show()
.end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
.removeAttr('style');
setupContentAndTriggerDisplay();
});
}
else {
$(settings.dom.revealID).hide(0, function () {
$(settings.dom.contentID).fadeOut(opts.fadeOutSpeed, function () {
$(settings.dom.wrapperID)
.find(settings.dom.revealElem + ',' + settings.dom.contentID)
.hide()
.end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
.show()
.end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
.removeAttr('style');
setupContentAndTriggerDisplay();
});
});
}
}
else {
$(settings.dom.revealElem).hide();
}
}
// pause ticker
function pauseTicker() {
settings.play = false;
// stop animation and show content - must pass "true, true" to the stop function, or we can get some funky behaviour
$(settings.dom.tickerID + ',' + settings.dom.revealID + ',' + settings.dom.titleID + ',' + settings.dom.titleElem + ',' + settings.dom.revealElem + ',' + settings.dom.contentID).stop(true, true);
$(settings.dom.revealID + ',' + settings.dom.revealElem).hide();
$(settings.dom.wrapperID)
.find(settings.dom.titleID + ',' + settings.dom.titleElem).show()
.end().find(settings.dom.contentID).show();
}
// play ticker
function restartTicker() {
settings.play = true;
settings.paused = false;
// start the ticker again
postReveal();
}
// change the content on user input
function manualChangeContent(direction) {
pauseTicker();
switch (direction) {
case 'prev':
if (settings.position == 0) {
settings.position = countSize(settings.newsArr) -2;
}
else if (settings.position == 1) {
settings.position = countSize(settings.newsArr) -1;
}
else {
settings.position = settings.position - 2;
}
$(settings.dom.titleElem).html(settings.newsArr['item-' + settings.position].type);
$(settings.dom.contentID).html(settings.newsArr['item-' + settings.position].content);
break;
case 'next':
$(settings.dom.titleElem).html(settings.newsArr['item-' + settings.position].type);
$(settings.dom.contentID).html(settings.newsArr['item-' + settings.position].content);
break;
}
// set the next content item to be used - loop round if we are at the end of the content
if (settings.position == (countSize(settings.newsArr) -1)) {
settings.position = 0;
}
else {
settings.position++;
}
}
});
};
// plugin defaults - added as a property on our plugin function
$.fn.ticker.defaults = {
speed: 0.10,
ajaxFeed: false,
feedUrl: '',
feedType: 'xml',
displayType: 'reveal',
htmlFeed: true,
debugMode: true,
controls: true,
titleText: '',
direction: 'ltr',
pauseOnItems: 3000,
fadeInSpeed: 600,
fadeOutSpeed: 300
};
})(jQuery);
/* Ticker Styling */
.ticker-wrapper.has-js {
margin: 0;
padding: 0;
width: 780px;
height: 32px;
display: block;
-webkit-border-radius: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
background-color:inherit;
font-size: inherit;
}
.ticker {
width: 710px;
height: 23px;
display: block;
position: relative;
overflow: hidden;
background-color: #fff;
#media #{$xs}{
width: 200px;
}
}
.ticker-title {
padding-top: 9px;
color: #990000;
font-weight: bold;
background-color: #fff;
text-transform: capitalize;
}
.ticker-content {
margin: 0px;
/* padding-top: 9px; */
position: absolute;
color: #506172;
font-weight: normal;
background-color: #fff;
overflow: hidden;
white-space: nowrap;
font-family: "Roboto",sans-serif;
font-size: 16px;
}
.ticker-content:focus {
none;
}
.ticker-content a {
text-decoration: none;
color: #1F527B;
}
.ticker-content a:hover {
text-decoration: underline;
color: #0D3059;
}
.ticker-swipe {
padding-top: 9px;
position: absolute;
top: 0px;
background-color: #fff;
display: block;
width: 800px;
height: 23px;
}
.ticker-swipe span {
margin-left: 1px;
background-color: #fff;
border-bottom: 1px solid #1F527B;
height: 12px;
width: 7px;
display: block;
}
.ticker-controls {
padding: 8px 0px 0px 0px;
list-style-type: none;
float: left;
}
.ticker-controls li {
padding: 0px;
margin-left: 5px;
float: left;
cursor: pointer;
height: 16px;
width: 16px;
display: block;
}
.ticker-controls li.jnt-play-pause {
background-image: url('../images/controls.png');
background-position: 32px 16px;
}
.ticker-controls li.jnt-play-pause.over {
background-position: 32px 32px;
}
.ticker-controls li.jnt-play-pause.down {
background-position: 32px 0px;
}
.ticker-controls li.jnt-play-pause.paused {
background-image: url('../images/controls.png');
background-position: 48px 16px;
}
.ticker-controls li.jnt-play-pause.paused.over {
background-position: 48px 32px;
}
.ticker-controls li.jnt-play-pause.paused.down {
background-position: 48px 0px;
}
.ticker-controls li.jnt-prev {
background-image: url('../images/controls.png');
background-position: 0px 16px;
}
.ticker-controls li.jnt-prev.over {
background-position: 0px 32px;
}
.ticker-controls li.jnt-prev.down {
background-position: 0px 0px;
}
.ticker-controls li.jnt-next {
background-image: url('../images/controls.png');
background-position: 16px 16px;
}
.ticker-controls li.jnt-next.over {
background-position: 16px 32px;
}
.ticker-controls li.jnt-next.down {
background-position: 16px 0px;
}
.js-hidden {
display: none;
}
.no-js-news {
padding: 10px 0px 0px 45px;
color: #fff;
}
.left .ticker-swipe {
/*left: 80px;*/
}
.left .ticker-controls, .left .ticker-content, .left .ticker-title, .left .ticker {
float: left;
}
.left .ticker-controls {
padding-left: 6px;
}
.right .ticker-swipe {
/*right: 80px;*/
}
.right .ticker-controls, .right .ticker-content, .right .ticker-title, .right .ticker {
float: right;
}
.right .ticker-controls {
padding-right: 6px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<strong>Trending now</strong>
<!-- <p>Rem ipsum dolor sit amet, consectetur adipisicing elit.</p> -->
<div class="trending-animated">
<ul id="js-news" class="js-hidden">
<li class="news-item">Dolor sit amet, consectetur adipisicing elit.</li>
<li class="news-item">Spondon IT sit amet, consectetur.......</li>
<li class="news-item">Rem ipsum dolor sit amet, consectetur adipisicing elit.</li>
</ul>
</div>
The problem is that you are setting fixed widths for ticker elements.The ticker container has a width of 720px no matter what size the screen, and on screens < 767px the container for the scrolling text is just 230px.
Either change the CSS if it is your own, or if not you can add these rules after the Ticker CSS in included:
#media (max-width: 767px){
.ticker-wrapper.has-js,
.ticker,
.trending-tittle .ticker {
width: 100%!important;
}
}
This sets them to use the full width of the screen.
I'm trying to implement my own confirmation box in JavaScript. But I don't want to change all the places where I have used window.confirm. So, I created proxy on window.confirm.
like,
(function (proxied) {
window.confirm = function () {
var res = MyConfirm.apply(this, arguments);
return res;
};
})(window.confirm);
The problem is, MyConfirm is based on promise but where ever confirm is there, its acting as boolean. What would be proper solution for this situation? Is it possible to make a custom function which works exactly like window.confirm?
Is there anyway, we can return boolean or other values from a function which depends on an async call?
You may be able to get the desired behavior with a custom confirmation dialog, I created a custom dialog control a while ago that gave me the ability to have a flexible modal confirmation dialog. I created a full sample jsFiddle here. For my needs, the dialog was part of a common js library and displays as soon as you instantiate it, and can include options for content, size, and confirmation button callbacks, but you could have a confirm function on the dialog object that does the work to initialize and display it, and return a response. Here's the complete code, which is also in the jsFiddle...
// Launch the dialog from a click on an element on the page
$("#launchDialog").click(function () {
showConfirmDialog();
})
function showConfirmDialog() {
//Define the dialog options
var dlgOptions = {
width: 300,
height: 150,
modal: true,
confirm: true,
confirmopts: {
closeOnOk: true,
question: "Are you sure?",
buttons: {
Ok: {
Label: "OK",
callback: dialogOkCallback
},
Cancel: {
Label: "Cancel",
callback: dialogCancelCallback
},
}
}
}
// Initialize the dialog object and display it
var dlg = MySite.Common.createDialog("confirmDialog", "Confirmation Required", "<p>Some additional dialog content here</p>", dlgOptions, document);
}
// Handle the OK response
function dialogOkCallback() {
$("#dialogresult").html("You clicked Ok");
}
// Handle the Cancel response
function dialogCancelCallback() {
$("#dialogresult").html("You clicked Cancel");
}
// Common library with dialog code
if (typeof (MySite) == "undefined")
{ MySite = { __namespace: true }; }
MySite.Common = {
createDialog: function (tagId, title, content, options, documentobj) {
var dlg;
var dlgLeft;
var dlgTop;
// Defaults
var dlgWidth = 210;
var dlgHeight = 140;
var dlgConfirmation = "";
var dlgConfirmationContainerHTML = "";
var dlgConfirmationContainer;
var isNewDialog;
var docBody;
var dlgTag;
var dlgModalBg;
var docObj;
// Take the document object passed in or default it, this is where the dialog div will be anchored
if (documentobj) {
docObj = documentobj;
}
else {
docObj = document;
}
docBody = $(docObj.body);
// Process the options if available
if (options) {
if (options.width) {
dlgWidth = options.width;
}
if (options.height) {
dlgHeight = options.height;
}
if (options.modal) {
// Set up the background div if this is a modal dialog
dlgModalBg = $(docObj.getElementById("dialogModalBackground"));
if (dlgModalBg.length == 0) {
docBody.append("<div id='dialogModalBackground' style='background-color: #000000; z-index:9998; position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; opacity: 0.3;'> </div>");
} else {
dlgModalBg = docBody.find("#dialogModalBackground");
dlgModalBg.show();
}
}
}
// Do some dialog positioning
dlgLeft = (docObj.body.clientWidth / 2) - (dlgWidth / 2);
dlgTop = (docObj.body.clientHeight / 2) - (dlgHeight / 2) - 50;
// Make sure the dialog top value doesn't go negative
dlgTop = Math.max(dlgTop, 0);
dlg = $(docObj.getElementById(tagId));
// Create the dialog div
if (dlg.length == 0) {
isNewDialog = true;
docBody.append("<div id='dialogContainer_" + tagId + "' style='width: " + dlgWidth + "px; min-height: " + dlgHeight + "px; background-color: #ffffff; border: 1px solid darkgrey; z-index: 9999; position: absolute; top: " + dlgTop + "px; left: " + dlgLeft + "px;'><p id='dlgHeader' class='draggable_handle' style='color: #FFFFFF; margin: 0px; padding: 5px 1px 1px 5px; height: 18px; background-color: #005f9f; font-weight: bold; font-size: 1.2em; font-family: Arial;'>" + title + "<span style='float: right; font-size: 0.8em; cursor: pointer; padding-right: 4px;' id='dialogClose_" + tagId + "'>Close</span></p><div style='padding: 0px; margin: 0px 2px 0px 2px; min-height: " + (dlgHeight - 24).toString() + "px;' id='" + tagId + "'></div></div>");
dlg = docBody.find("#" + tagId);
} else {
isNewDialog = false;
dlg.html("");
docBody.find("#dialogContainer_" + tagId).show();
}
// Make the dialog draggable if that feature is available
if ($.ui) {
if ($.ui.draggable) {
docBody.find("#dlgHeader").css("cursor", "move");
docBody.find("#dialogContainer_" + tagId).draggable({ handle: ".draggable_handle" });
}
}
if (content) {
dlg.html(content);
}
// Create or update the confirmation dialog content
dlgConfirmationContainer = docBody.find("#Confirmation_" + tagId);
// Set up the buttons if this is a confirmation dialog
if (options.confirm == true) {
if (options.confirmopts.question != null) {
dlgConfirmation += options.confirmopts.question + "<br/><br/>";
}
if (options.confirmopts.buttons.Ok.Label != null) {
dlgConfirmation += "<input id='dialogOk_" + tagId + "' style='width: 45%' type='button' value='" + options.confirmopts.buttons.Ok.Label + "'/> ";
}
if (options.confirmopts.buttons.Cancel != null && options.confirmopts.buttons.Cancel.Label != null) {
dlgConfirmation += "<input id='dialogCancel_" + tagId + "' style='width: 45%' type='button' value='" + options.confirmopts.buttons.Cancel.Label + "'/>";
}
if (dlgConfirmationContainer.length == 0) {
dlg.append("<div id='Confirmation_" + tagId + "' style='padding: 3px'>" + dlgConfirmation + "</div>");
} else {
dlgConfirmationContainer.show();
dlgConfirmationContainer.html(dlgConfirmation);
}
} else {
dlgConfirmationContainer.hide();
}
// Assign click events if this is a confirmation dialog. the jQuery click() assignment normally would APPEND click events to
// the object, but those are lost when the div container html is reassigned above, so we assign the click each time this function
// is called.
if (options.confirm) {
docBody.find("#dialogOk_" + tagId).click(function (event) {
event.preventDefault();
if (options.confirmopts.closeOnOk == true) {
docBody.find("#dialogContainer_" + tagId).hide();
docBody.find("#dialogModalBackground").hide();
}
if (!options.confirmopts.keepOnOk) {
docBody.find("#Confirmation_" + tagId).hide();
}
if (options.confirmopts.buttons.Ok.callback != null) {
options.confirmopts.buttons.Ok.callback();
}
});
docBody.find("#dialogCancel_" + tagId).click(function (event) {
event.preventDefault();
docBody.find("#dialogContainer_" + tagId).hide();
docBody.find("#dialogModalBackground").hide();
if (options.confirmopts.buttons.Cancel.callback != null) {
options.confirmopts.buttons.Cancel.callback();
}
});
}
docBody.find("#dialogClose_" + tagId).click(function (event) {
event.preventDefault();
docBody.find("#dialogContainer_" + tagId).hide();
docBody.find("#dialogModalBackground").hide();
});
dlg.closeDialog = function () {
docBody.find("#dialogContainer_" + tagId).hide();
docBody.find("#dialogModalBackground").hide();
};
return dlg;
},
__namespace: true
};
I'm using CoverPop to display a popup to my customers. Everything seems so easy but somehow I'm to dumb to make the popup closeable. I have inserted a "close" link, as described in the setup. However when I click on it, nothing happens.
Only way to close the popup is by pressing the escape key on my keyboard.
I know this must be ridiculous for some of you. I'd really appreciate some help though.
Thanks.
HTML
<script>
CoverPop.start({});
</script>
<div id="CoverPop-cover" class="splash">
<div class="CoverPop-content splash-center">
<h2 class="splash-title">Willkommen bei Exsys <span class="bold">Schweiz</span></h2>
<p class="splash-intro">Kunden aus Deutschland und anderen EU-Ländern wechseln bitte zu unserer <span class="bold">deutschen</span> Seite.</p>
<img src="{$ShopURL}/templates/xt_grid/img/shop-ch.png" title="EXSYS Online-Shop Schweiz" height="60" style="margin: 0 20px 0 0;" alt="Schweizer Exsys-Shop"/>
<img src="{$ShopURL}/templates/xt_grid/img/shop-de.png" height="60" alt="Shop Deutschland"/>
<p class="close-splash"><a class="CoverPop-close" href="#">Close</a></p>
</div><!--end .splash-center -->
</div><!--end .splash -->
CSS
.CoverPop-open,
.CoverPop-open body {
overflow: hidden;
}
#CoverPop-cover {
display: none;
position: fixed;
overflow-y: scroll;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1000;
-webkit-animation: fade-in .25s ease-in;
-moz-animation-name: fade-in .25s ease-in;
-ms-animation-name: fade-in .25s ease-in;
-o-animation-name: fade-in .25s ease-in;
animation-name: fade-in .25s ease-in;
}
.CoverPop-open #CoverPop-cover {
display: block;
}
.splash {
background-color:rgba(47, 99, 135, 0.9);
}
.splash-center {
background-color: white;
border-right: 8px solid #007ec8;
border-bottom: 8px solid #007ec8;
border-left: 8px solid #007ec8;
margin: 15px;
text-align: center;
top: 7px;
width: 15%;
}
.splash-center p{
margin: 20px 10px;
}
.splash-center h2{
font-size:16px;
width: 100%;
background:#007ec8;
padding: 10px 0;
color:#FFF;
}
JS
(function (CoverPop, undefined) {
'use strict';
// set default settings
var settings = {
// set default cover id
coverId: 'CoverPop-cover',
// duration (in days) before it pops up again
expires: 30,
// close if someone clicks an element with this class and prevent default action
closeClassNoDefault: 'CoverPop-close',
// close if someone clicks an element with this class and continue default action
closeClassDefault: 'CoverPop-close-go',
// change the cookie name
cookieName: '_ExsPop',
// on popup open function callback
onPopUpOpen: null,
// on popup close function callback
onPopUpClose: null,
// hash to append to url to force display of popup
forceHash: 'splash',
// hash to append to url to delay popup for 1 day
delayHash: 'go',
// close if the user clicks escape
closeOnEscape: true,
// set an optional delay (in milliseconds) before showing the popup
delay: 2000,
// automatically close the popup after a set amount of time (in milliseconds)
hideAfter: null
},
// grab the elements to be used
$el = {
html: document.getElementsByTagName('html')[0],
cover: document.getElementById(settings.coverId),
closeClassDefaultEls: document.querySelectorAll('.' + settings.closeClassDefault),
closeClassNoDefaultEls: document.querySelectorAll('.' + settings.closeClassNoDefault)
},
/**
* Helper methods
*/
util = {
hasClass: function(el, name) {
return new RegExp('(\\s|^)' + name + '(\\s|$)').test(el.className);
},
addClass: function(el, name) {
if (!util.hasClass(el, name)) {
el.className += (el.className ? ' ' : '') + name;
}
},
removeClass: function(el, name) {
if (util.hasClass(el, name)) {
el.className = el.className.replace(new RegExp('(\\s|^)' + name + '(\\s|$)'), ' ').replace(/^\s+|\s+$/g, '');
}
},
addListener: function(target, type, handler) {
if (target.addEventListener) {
target.addEventListener(type, handler, false);
} else if (target.attachEvent) {
target.attachEvent('on' + type, handler);
}
},
removeListener: function(target, type, handler) {
if (target.removeEventListener) {
target.removeEventListener(type, handler, false);
} else if (target.detachEvent) {
target.detachEvent('on' + type, handler);
}
},
isFunction: function(functionToCheck) {
var getType = {};
return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
},
setCookie: function(name, days) {
var date = new Date();
date.setTime(+ date + (days * 86400000));
document.cookie = name + '=true; expires=' + date.toGMTString() + '; path=/';
},
hasCookie: function(name) {
if (document.cookie.indexOf(name) !== -1) {
return true;
}
return false;
},
// check if there is a hash in the url
hashExists: function(hash) {
if (window.location.hash.indexOf(hash) !== -1) {
return true;
}
return false;
},
preventDefault: function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
mergeObj: function(obj1, obj2) {
for (var attr in obj2) {
obj1[attr] = obj2[attr];
}
}
},
/**
* Private Methods
*/
// close popup when user hits escape button
onDocUp = function(e) {
if (settings.closeOnEscape) {
if (e.keyCode === 27) {
CoverPop.close();
}
}
},
openCallback = function() {
// if not the default setting
if (settings.onPopUpOpen !== null) {
// make sure the callback is a function
if (util.isFunction(settings.onPopUpOpen)) {
settings.onPopUpOpen.call();
} else {
throw new TypeError('CoverPop open callback must be a function.');
}
}
},
closeCallback = function() {
// if not the default setting
if (settings.onPopUpClose !== null) {
// make sure the callback is a function
if (util.isFunction(settings.onPopUpClose)) {
settings.onPopUpClose.call();
} else {
throw new TypeError('CoverPop close callback must be a function.');
}
}
};
/**
* Public methods
*/
CoverPop.open = function() {
var i, len;
if (util.hashExists(settings.delayHash)) {
util.setCookie(settings.cookieName, 1); // expire after 1 day
return;
}
util.addClass($el.html, 'CoverPop-open');
// bind close events and prevent default event
if ($el.closeClassNoDefaultEls.length > 0) {
for (i=0, len = $el.closeClassNoDefaultEls.length; i < len; i++) {
util.addListener($el.closeClassNoDefaultEls[i], 'click', function(e) {
if (e.target === this) {
util.preventDefault(e);
CoverPop.close();
}
});
}
}
// bind close events and continue with default event
if ($el.closeClassDefaultEls.length > 0) {
for (i=0, len = $el.closeClassDefaultEls.length; i < len; i++) {
util.addListener($el.closeClassDefaultEls[i], 'click', function(e) {
if (e.target === this) {
CoverPop.close();
}
});
}
}
// bind escape detection to document
util.addListener(document, 'keyup', onDocUp);
openCallback();
};
CoverPop.close = function(e) {
util.removeClass($el.html, 'CoverPop-open');
util.setCookie(settings.cookieName, settings.expires);
// unbind escape detection to document
util.removeListener(document, 'keyup', onDocUp);
closeCallback();
};
CoverPop.init = function(options) {
if (navigator.cookieEnabled) {
util.mergeObj(settings, options);
// check if there is a cookie or hash before proceeding
if (!util.hasCookie(settings.cookieName) || util.hashExists(settings.forceHash)) {
if (settings.delay === 0) {
CoverPop.open();
} else {
// delay showing the popup
setTimeout(CoverPop.open, settings.delay);
}
if (settings.hideAfter) {
// hide popup after the set amount of time
setTimeout(CoverPop.close, settings.hideAfter + settings.delay);
}
}
}
};
// alias
CoverPop.start = function(options) {
CoverPop.init(options);
};
}(window.CoverPop = window.CoverPop || {}));
Additional information
I quickly checked my site and these are the sections I found where the click event is present. Honestly I have no idea how they do interfere with the popup.
// tabs
$('ul.tabs').each(function(){
var $active, $content, $links = $(this).find('a');
$active = $links.first().addClass('active');
$content = $($active.attr('rel'));
$links.not(':first').each(function () {
$($(this).attr('rel')).hide();
});
$(this).on('click', 'a', function(e){
$active.removeClass('active');
$content.hide();
$active = $(this);
$content = $($(this).attr('rel'));
$active.addClass('active');
$content.show();
e.preventDefault();
});
});
// track box clicks and route them to parent radio button
$('div.box-hover').click( function(e)
{
$(this).find("input[type=radio]").click();
});
$('input[type=radio]').click(function(e){
if (this.checked != true && $(this).hasClass('autosubmit')){
this.checked = true;
this.form.submit();
}
e.stopPropagation();
});
// track box clicks to show/hide some desc (shipping/payment)
$('div.box-hover').click( function(e)
{
// ok. wir wollen clicks auf shipping abfangen
// und - laut tmpl - kann nur EIN passendes kind da sein
// also geht das mit dem length check!
if( $(this).children('p.shipping-name').length > 0)
{
$('div.box-hover').children('p.shipping-desc').css('display','none');
$(this).children('p.shipping-desc').css('display','block');
}
if( $(this).children('p.payment-name').length > 0)
{
$('div.box-hover').children('p.payment-desc').css('display','none');
$(this).children('p.payment-desc').css('display','block');
}
});
// autosize the comment textarea
$('#comments').autosize();
// slide in/out guest account form
$("#guest").click( function(e){
$("#cust_info_customers_password").val('');
$("#cust_info_customers_password_confirm").val('');
$('#guest-account').slideUp(250);
});
$("#account").click( function(e){
$('#guest-account').slideDown(250);
});
});
#santadani, found there is a rule to follow due to the implmentation of CoverPop itself. from your production environment, could you move the <script type="text/javascript" src="http://www.exsys.ch/templates/xt_grid/javascript/CoverPop.js"></script> to the end of document, before the </body> tag and try again?
It is because i saw in the CoverPop source, it grabs the element upon the script is loaded
$el = {
html: document.getElementsByTagName('html')[0],
cover: document.getElementById(settings.coverId),
closeClassDefaultEls: document.querySelectorAll('.' + settings.closeClassDefault),
closeClassNoDefaultEls: document.querySelectorAll('.' + settings.closeClassNoDefault)
},
which then the document.querySelectorAll('.' + settings.closeClassDefault) will retrieve nothing (becasue the script was loaded before the DOM are ready, therefore i suggest to try to move the script tag down)
I have a simple memory game that is won by matching two letter. How can I add a button to start a timer that displays some where by the game, and when you win the timer stops but shows best times, furthermore, you can keep count to beat your best time. Also, how do I change my letter to substitute for images?
<title>Memory</title>
</head>
<body>
<div id="container">
<div id="header">
Memory!
</div>
<div id="content">
<table id="gameBoard">
<tbody>
</tbody>
</table>
<button id="playAgain">Play Again</button>
</div>
</div>
body {
font-family:copperplate;
font-size: 0.9em;
background-color:#ccc;
}
html, body {
margin:0;
padding:0;
height:100%;
}
#container {
width:950px;
min-width:950px;
background-color:#fff;
margin:0 auto;
min-height:100%;
}
#header {
font-size:4em;
line-height:95px;
text-align:center;
border-bottom:1px solid #000;
}
#content {
clear:both;
border-top:1px solid #000;
padding-top:5px;
padding:10px;
text-align:center;
}
h1 {
text-transform: capitalize;
}
#gameBoard {
margin-left:auto;
margin-right:auto;
margin-bottom:25px;
}
.card {
width:100px;
height:100px;
border:1px solid #000;
cursor: pointer;
}
.down {
background-color: #E8DD5B;
}
.up {
background-color: #ccc;
line-height: 100px;
text-align:center;
font-size:5em;
}
button {
font-size:2em;
padding:5px;
background-color:#E97A54;
}
$(function() {
var cards = [
{ id: 1, matchesId: 2, content: "A" },
{ id: 2, matchesId: 1, content: "A" },
{ id: 3, matchesId: 4, content: "B" },
{ id: 4, matchesId: 3, content: "B" },
{ id: 5, matchesId: 6, content: "C" },
{ id: 6, matchesId: 5, content: "C" },
{ id: 7, matchesId: 8, content: "D" },
{ id: 8, matchesId: 7, content: "D" },
{ id: 9, matchesId: 10, content: "E" },
{ id: 10, matchesId: 9, content: "E" },
{ id: 11, matchesId: 12, content: "F" },
{ id: 12, matchesId: 11, content: "F" }
];
var shuffledCards = [];
var cardToMatchElement;
setupGame();
$("#playAgain").click(function() {
setupGame();
});
function setupGame() {
cardToMatchElement = null;
shuffleCards();
dealCards();
}
function shuffleCards() {
shuffledCards = [];
for(var i = 0; i < cards.length; i++) {
var randomCardIndex = getRandomCardIndex();
while($.inArray(randomCardIndex,shuffledCards) != -1) {
randomCardIndex = getRandomCardIndex();
}
shuffledCards.push(randomCardIndex);
}
}
function getRandomCardIndex() {
return Math.floor((Math.random() * cards.length));
}
function dealCards() {
setupGameBoard();
attachCardEvents();
}
function attachCardEvents() {
$(".card").click(function() {
var selectedCardElement = $(this);
var selectedCard = getCardFromElement(selectedCardElement);
flipCard(selectedCardElement, selectedCard);
if(cardToMatchElement) {
var cardToMatch = getCardFromElement(cardToMatchElement);
if(cardToMatch.matchesId == selectedCard.id) {
selectedCardElement.off();
cardToMatchElement.off();
cardToMatchElement = null;
}
else {
$.blockUI({ message: "", overlayCSS : { backgroundColor: '#fff', cursor:'normal', opacity:0.5 } });
setTimeout(function() {
flipCard(selectedCardElement, selectedCard);
flipCard(cardToMatchElement, cardToMatch);
cardToMatchElement = null;
$.unblockUI();
},1000);
}
}
else {
cardToMatchElement = selectedCardElement;
}
});
}
function getCardFromElement(cardElement) {
return cards[cardElement.attr("data-cardindex")];
}
function flipCard(cardElement, card) {
if(cardElement.hasClass("down")) {
cardElement.removeClass("down").addClass("up");
cardElement.html(card.content);
}
else {
cardElement.removeClass("up").addClass("down");
cardElement.html("");
}
}
function setupGameBoard() {
var numberColumns = 4;
var tableBody = "";
var tableRow = "<tr>";
$.each(shuffledCards, function(index, card) {
tableRow += "<td><div class='card down' data-cardindex='" + shuffledCards[index] + "'> </div></td>";
if(index > 0 && (index + 1) % numberColumns == 0) {
tableRow += "</tr>";
if(index < cards.length - 1) {
tableRow += "<tr>";
}
}
if(index == cards.length - 1 && (index + 1) % numberColumns != 0) {
tableRow += "</tr>";
}
tableBody += tableRow;
tableRow = "";
});
$("#gameBoard tbody").html(tableBody);
}
});
http://jsfiddle.net/Brannan2/VkKRa/1/
To create a timer call below function on your button click (id is some global js variable)
function createTimer() {
id = setInterval(function(){
var secondEl = document.getElementById('second');
if (secondEl.value == null || secondEl.value == "") {
secondEl.value = 0;
}
var seconds = parseInt(secondEl.value) + 1;
if (seconds == 60) {
seconds = 0;
var minuteEl = document.getElementById('minute');
if (minuteEl.value == null || minuteEl.value == "") {
minuteEl.value = 0;
}
var minutes = parseInt(minuteEl.value) + 1;
if (minutes == 60) {
minutes = 0;
var hourEl = document.getElementById('hour');
if (hourEl.value == null || hourEl.value == "") {
hourEl.value = 0;
}
hourEl.value = parseInt(hourEl.value) + 1;
}
minuteEl.value = minutes;
}
secondEl.value = seconds;
},1000);
}
For my sample I have created three input types in html with ids 'hour','minute' and 'second'. You can create any other based on UI need and update function accordingly.
To stop timer just remove the setInterval function as shown below
window.clearInterval(id);
Once you have stop the watch you can calculate total times easily by using below formula
var totalTime = (hours * 3600) + (minutes * 60) + seconds;
This will return the total time in seconds. Now to get best times, I think you have to use localStorage so that you can store best times in client browser and refer to it later whenever user returns again to play your game.
To substitute letter with images, there can be many ways. For e.g. you can add a css class to the element which will set the background image for you or you can directly use a img tag in your div with image location. Its totally up to you. I am not sure though why you want to show image with your current requirement.