Related
Hy there! I plan to use Rater.js in my project and so far I am happy with the library. There is only one issue I can't resolve alone. Pls. take a look at
https://jsfiddle.net/herbert_hinterberger/r1cgnpt3/.
At the very bottom of the script, I defined step_size: 1.
(".rating").rate();
//or for example
var options = {
max_value: 5,
step_size: 1,
}
Now I would expect that when I hover over the stars, only full stars are selected. But still, half stars are selected too. Any Idea what I a doing wrong?
In your example code, you are calling $(".rating").rate(); without options (line number 499).
After commenting it, you will end-up with something like below
/*
* A highly customizable rating widget that supports images, utf8 glyphs and other html elements!
* https://github.com/auxiliary/rater
*/
; (function ($, window) {
$.fn.textWidth = function () {
var html_calc = $('<span>' + $(this).html() + '</span>');
html_calc.css('font-size', $(this).css('font-size')).hide();
html_calc.prependTo('body');
var width = html_calc.width();
html_calc.remove();
if (width == 0) {
var total = 0;
$(this).eq(0).children().each(function () {
total += $(this).textWidth();
});
return total;
}
return width;
};
$.fn.textHeight = function () {
var html_calc = $('<span>' + $(this).html() + '</span>');
html_calc.css('font-size', $(this).css('font-size')).hide();
html_calc.prependTo('body');
var height = html_calc.height();
html_calc.remove();
return height;
};
/*
* IE8 doesn't support isArray!
*/
Array.isArray = function (obj) {
return Object.prototype.toString.call(obj) === "[object Array]";
};
/*
* Utf-32 isn't supported by default, so we have to use Utf-8 surrogates
*/
String.prototype.getCodePointLength = function () {
return this.length - this.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g).length + 1;
};
String.fromCodePoint = function () {
var chars = Array.prototype.slice.call(arguments);
for (var i = chars.length; i-- > 0;) {
var n = chars[i] - 0x10000;
if (n >= 0)
chars.splice(i, 1, 0xD800 + (n >> 10), 0xDC00 + (n & 0x3FF));
}
return String.fromCharCode.apply(null, chars);
};
/*
* Starting the plugin itself
*/
$.fn.rate = function (options) {
if (options === undefined || typeof options === 'object') {
return this.each(function () {
if (!$.data(this, "rate")) {
$.data(this, "rate", new Rate(this, options));
}
});
}
else if (typeof options === 'string') {
var args = arguments;
var returns;
this.each(function () {
var instance = $.data(this, "rate");
if (instance instanceof Rate && typeof instance[options] === 'function') {
returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
}
if (options === 'destroy') {
// Unbind all events and empty the plugin data from instance
$(instance.element).off();
$.data(this, 'rate', null);
}
});
return returns !== undefined ? returns : this;
}
};
function Rate(element, options) {
this.element = element;
this.settings = $.extend({}, $.fn.rate.settings, options);
this.set_faces = {}; // value, symbol pairs
this.build();
}
Rate.prototype.build = function () {
this.layers = {};
this.value = 0;
this.raise_select_layer = false;
if (this.settings.initial_value) {
this.value = this.settings.initial_value;
}
if ($(this.element).attr("data-rate-value")) {
this.value = $(this.element).attr("data-rate-value");
}
/*
* Calculate the selected width based on the initial value
*/
var selected_width = this.value / this.settings.max_value * 100;
/*
* Let's support single strings as symbols as well as objects
*/
if (typeof this.settings.symbols[this.settings.selected_symbol_type] === 'string') {
var symbol = this.settings.symbols[this.settings.selected_symbol_type];
this.settings.symbols[this.settings.selected_symbol_type] = {};
this.settings.symbols[this.settings.selected_symbol_type]['base'] = symbol;
this.settings.symbols[this.settings.selected_symbol_type]['selected'] = symbol;
this.settings.symbols[this.settings.selected_symbol_type]['hover'] = symbol;
}
/*
* Making the three main layers (base, select, hover)
*/
var base_layer = this.addLayer("base-layer", 100, this.settings.symbols[
this.settings.selected_symbol_type]["base"], true);
var select_layer = this.addLayer("select-layer", selected_width,
this.settings.symbols[this.settings.selected_symbol_type]["selected"], true);
var hover_layer = this.addLayer("hover-layer", 0, this.settings.symbols[
this.settings.selected_symbol_type]["hover"], false);
/* var face_layer = this.addLayer("face-layer", 1, this.settings
.symbols[this.settings.face_layer_symbol_type][0], true); */
this.layers["base_layer"] = base_layer;
this.layers["select_layer"] = select_layer;
this.layers["hover_layer"] = hover_layer;
/*
* Bind the container to some events
*/
$(this.element).on("mousemove", $.proxy(this.hover, this));
$(this.element).on("click", $.proxy(this.select, this));
$(this.element).on("mouseleave", $.proxy(this.mouseout, this));
/*
* Set the main element as unselectable
*/
$(this.element).css({
"-webkit-touch-callout": "none",
"-webkit-user-select": "none",
"-khtml-user-select": "none",
"-moz-user-select": "none",
"-ms-user-select": "none",
"user-select": "none",
});
/*
* Update custom input field if provided
*/
if (this.settings.hasOwnProperty("update_input_field_name")) {
this.settings.update_input_field_name.val(this.value);
}
}
/*
* Function to add a layer
*/
Rate.prototype.addLayer = function (layer_name, visible_width, symbol, visible) {
var layer_body = "<div>";
for (var i = 0; i < this.settings.max_value; i++) {
if (Array.isArray(symbol)) {
if (this.settings.convert_to_utf8) {
symbol[i] = String.fromCodePoint(symbol[i]);
}
layer_body += "<span>" + (symbol[i]) + "</span>";
}
else {
if (this.settings.convert_to_utf8) {
symbol = String.fromCodePoint(symbol);
}
layer_body += "<span>" + symbol + "</span>";
}
}
layer_body += "</div>";
var layer = $(layer_body).addClass("rate-" + layer_name).appendTo(this.element);
$(layer).css({
width: visible_width + "%",
height: $(layer).children().eq(0).textHeight(),
overflow: 'hidden',
position: 'absolute',
top: 0,
display: visible ? 'block' : 'none',
'white-space': 'nowrap'
});
$(this.element).css({
width: $(layer).textWidth() + "px",
height: $(layer).height(),
position: 'relative',
cursor: this.settings.cursor,
});
return layer;
}
Rate.prototype.updateServer = function () {
if (this.settings.url != undefined) {
$.ajax({
url: this.settings.url,
type: this.settings.ajax_method,
data: $.extend({}, { value: this.getValue() }, this.settings.additional_data),
success: $.proxy(function (data) {
$(this.element).trigger("updateSuccess", [data]);
}, this),
error: $.proxy(function (jxhr, msg, err) {
$(this.element).trigger("updateError", [jxhr, msg, err]);
}, this)
});
}
}
Rate.prototype.getValue = function () {
return this.value;
}
Rate.prototype.hover = function (ev) {
var pad = parseInt($(this.element).css("padding-left").replace("px", ""));
var x = ev.pageX - $(this.element).offset().left - pad;
var val = this.toValue(x, true);
if (val != this.value) {
this.raise_select_layer = false;
}
if (!this.raise_select_layer && !this.settings.readonly) {
var visible_width = this.toWidth(val);
this.layers.select_layer.css({ display: 'none' });
if (!this.settings.only_select_one_symbol) {
this.layers.hover_layer.css({
width: visible_width + "%",
display: 'block'
});
}
else {
var index_value = Math.floor(val);
this.layers.hover_layer.css({
width: "100%",
display: 'block'
});
this.layers.hover_layer.children("span").css({
visibility: 'hidden',
});
this.layers.hover_layer.children("span").eq(index_value != 0 ? index_value - 1 : 0).css({
visibility: 'visible',
});
}
}
}
/*
* Event for when a rating has been selected (clicked)
*/
Rate.prototype.select = function (ev) {
if (!this.settings.readonly) {
var old_value = this.getValue();
var pad = parseInt($(this.element).css("padding-left").replace("px", ""));
var x = ev.pageX - $(this.element).offset().left - pad;
var selected_width = this.toWidth(this.toValue(x, true));
this.setValue(this.toValue(selected_width));
this.raise_select_layer = true;
}
}
Rate.prototype.mouseout = function () {
this.layers.hover_layer.css({ display: 'none' });
this.layers.select_layer.css({ display: 'block' });
}
/*
* Takes a width (px) and returns the value it resembles
*/
Rate.prototype.toWidth = function (val) {
return val / this.settings.max_value * 100;
}
/*
* Takes a value and calculates the width of the selected/hovered layer
*/
Rate.prototype.toValue = function (width, in_pixels) {
var val;
if (in_pixels) {
val = width / this.layers.base_layer.textWidth() * this.settings.max_value;
}
else {
val = width / 100 * this.settings.max_value;
}
// Make sure the division doesn't cause some small numbers added by
// comparing to a small arbitrary number.
var temp = val / this.settings.step_size;
if (temp - Math.floor(temp) < 0.00005) {
val = Math.round(val / this.settings.step_size) * this.settings.step_size;
}
val = (Math.ceil(val / this.settings.step_size)) * this.settings.step_size;
val = val > this.settings.max_value ? this.settings.max_value : val;
return val;
}
Rate.prototype.getElement = function (layer_name, index) {
return $(this.element).find(".rate-" + layer_name + " span").eq(index - 1);
}
Rate.prototype.getLayers = function () {
return this.layers;
}
Rate.prototype.setFace = function (value, face) {
this.set_faces[value] = face;
}
Rate.prototype.setAdditionalData = function (data) {
this.settings.additional_data = data;
}
Rate.prototype.getAdditionalData = function () {
return this.settings.additional_data;
}
Rate.prototype.removeFace = function (value) {
delete this.set_faces[value];
}
Rate.prototype.setValue = function (value) {
if (!this.settings.readonly) {
if (value < 0) {
value = 0;
}
else if (value > this.settings.max_value) {
value = this.settings.max_value;
}
var old_value = this.getValue();
this.value = value;
/*
* About to change event, should support prevention later
*/
var change_event = $(this.element).trigger("change", {
"from": old_value,
"to": this.value
});
/*
* Set/Reset faces
*/
$(this.element).find(".rate-face").remove();
$(this.element).find("span").css({
visibility: 'visible'
});
var index_value = Math.ceil(this.value);
if (this.set_faces.hasOwnProperty(index_value)) {
var face = "<div>" + this.set_faces[index_value] + "</div>";
var base_layer_element = this.getElement('base-layer', index_value);
var select_layer_element = this.getElement('select-layer', index_value);
var hover_layer_element = this.getElement('hover-layer', index_value);
var left_pos = base_layer_element.textWidth() * (index_value - 1)
+ (base_layer_element.textWidth() - $(face).textWidth()) / 2;
$(face).appendTo(this.element).css({
display: 'inline-block',
position: 'absolute',
left: left_pos,
}).addClass("rate-face");
base_layer_element.css({
visibility: 'hidden'
});
select_layer_element.css({
visibility: 'hidden'
});
hover_layer_element.css({
visibility: 'hidden'
});
}
/*
* Set styles based on width and value
*/
if (!this.settings.only_select_one_symbol) {
var width = this.toWidth(this.value);
this.layers.select_layer.css({
display: 'block',
width: width + "%",
height: this.layers.base_layer.css("height")
});
this.layers.hover_layer.css({
display: 'none',
height: this.layers.base_layer.css("height")
});
}
else {
var width = this.toWidth(this.settings.max_value);
this.layers.select_layer.css({
display: 'block',
width: width + "%",
height: this.layers.base_layer.css("height")
});
this.layers.hover_layer.css({
display: 'none',
height: this.layers.base_layer.css("height")
});
this.layers.select_layer.children("span").css({
visibility: 'hidden',
});
this.layers.select_layer.children("span").eq(index_value != 0 ? index_value - 1 : 0).css({
visibility: 'visible',
});
}
// Update the data-rate-value attribute
$(this.element).attr("data-rate-value", this.value);
if (this.settings.change_once) {
this.settings.readonly = true;
}
this.updateServer();
/*
* After change event
*/
var change_event = $(this.element).trigger("afterChange", {
"from": old_value,
"to": this.value
});
/*
* Update custom input field if provided
*/
if (this.settings.hasOwnProperty("update_input_field_name")) {
this.settings.update_input_field_name.val(this.value);
}
}
}
Rate.prototype.increment = function () {
this.setValue(this.getValue() + this.settings.step_size);
}
Rate.prototype.decrement = function () {
this.setValue(this.getValue() - this.settings.step_size);
}
$.fn.rate.settings = {
max_value: 5,
step_size: 0.5,
initial_value: 0,
symbols: {
utf8_star: {
base: '\u2606',
hover: '\u2605',
selected: '\u2605',
},
utf8_hexagon: {
base: '\u2B21',
hover: '\u2B22',
selected: '\u2B22',
},
hearts: '♥',
fontawesome_beer: '<i class="fa fa-beer"></i>',
fontawesome_star: {
base: '<i class="fa fa-star-o"></i>',
hover: '<i class="fa fa-star"></i>',
selected: '<i class="fa fa-star"></i>',
},
utf8_emoticons: {
base: [0x1F625, 0x1F613, 0x1F612, 0x1F604],
hover: [0x1F625, 0x1F613, 0x1F612, 0x1F604],
selected: [0x1F625, 0x1F613, 0x1F612, 0x1F604],
},
},
selected_symbol_type: 'utf8_star', // Must be a key from symbols
convert_to_utf8: false,
cursor: 'default',
readonly: false,
change_once: false, // Determines if the rating can only be set once
only_select_one_symbol: false, // If set to true, only selects the hovered/selected symbol and nothing prior to it
ajax_method: 'POST',
additional_data: {}, // Additional data to send to the server
//update_input_field_name = some input field set by the user
};
}(jQuery, window));
//$(".rating").rate();
//or for example
var options = {
max_value: 5,
step_size: 1,
}
$(".rating").rate(options);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="rating" data-rate-value=6></div>
You are specifying the options at an earlier stage in your code.
See here:
$.fn.rate.settings = {
max_value: 5,
step_size: 0.5,
I tested in your fiddle and it works when updated to 1 step_size.
I'm working on an existing popunder script and it works great but the problem is that it triggers even if the cookie is set, its not supposed to trigger if the cookie is set and I can't figure it out how to solve this, I want it to trigger once every 1 hour, thanks
/**
* Smart Popunder maker.
* This class provides an easy way to make a popunder.
* Avoid blocked on Google Chrome
*
* Note: For Google Chrome, to avoid blocked so each popunder will be fired by each click.
*
* #author: Phan Thanh Cong aka chiplove <ptcong90#gmail.com>
* #license: MIT
*
* Edit by: Rafel Sansó <rafel.sanso#gmail.com>
*
* Changelog
*
* version 2.3.2.1; Apr 23, 2015
* - Eventually, the popup doesn't launch. To prevent this I comment lines 174, 180 and 208
*
*/
(function(window){
"use strict";
var Popunder = function(url, options){ this.__construct(url, options); },
counter = 0,
lastPopTime = 0,
alertCalled = false,
baseName = 'ChipPopunder',
parent = top != self ? top : self,
userAgent = navigator.userAgent.toLowerCase(),
browser = {
webkit: /webkit/.test(userAgent),
mozilla: /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent),
chrome: /chrome/.test(userAgent),
msie: /msie|trident\//.test(userAgent) && !/opera/.test(userAgent),
firefox: /firefox/.test(userAgent),
safari: /safari/.test(userAgent) && !/chrome/.test(userAgent),
opera: /opera/.test(userAgent),
version: parseInt(userAgent.match(/(?:[^\s]+(?:ri|ox|me|ra)\/|trident\/.*?rv:)([\d]+)/i)[1], 10)
},
helper = {
simulateClick: function(url) {
var a = document.createElement("a"),
nothing = "",
evt = document.createEvent("MouseEvents");
a.href = url || "data:text/html,<script>window.close();<\/script>;";
document.body.appendChild(a);
evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, true, false, false, true, 0, null);
a.dispatchEvent(evt);
a.parentNode.removeChild(a);
},
blur: function(popunder) {
try {
popunder.blur();
popunder.opener.window.focus();
window.self.window.focus();
window.focus();
if (browser.firefox) {
this.openCloseWindow(popunder);
} else if (browser.webkit) {
// try to blur popunder window on chrome
// but not works on chrome 41
// so we should wrap this to avoid chrome display warning
if (!browser.chrome || (browser.chrome && browser.version < 41)) {
this.openCloseTab();
}
} else if (browser.msie) {
setTimeout(function() {
popunder.blur();
popunder.opener.window.focus();
window.self.window.focus();
window.focus();
}, 1000);
}
} catch(err) {}
},
openCloseWindow: function(popunder) {
var tmp = popunder.window.open("about:blank");
tmp.focus();
tmp.close();
setTimeout(function() {
try {
tmp = popunder.window.open("about:blank");
tmp.focus();
tmp.close();
} catch (e) {}
}, 1);
},
openCloseTab: function() {
this.simulateClick();
},
detachEvent: function(event, callback, object) {
var object = object || window;
if (!object.removeEventListener) {
return object.detachEvent("on" + event, callback);
}
return object.removeEventListener(event, callback);
},
attachEvent: function(event, callback, object) {
var object = object || window;
if (!object.addEventListener) {
return object.attachEvent("on" + event, callback);
}
return object.addEventListener(event, callback);
},
mergeObject: function() {
var obj = {}, i, k;
for(i = 0; i < arguments.length; i++) {
for (k in arguments[i]) {
obj[k] = arguments[i][k];
}
}
return obj;
},
getCookie: function(name) {
var cookieMatch = document.cookie.match(new RegExp(name+"=[^;]+", "i"));
return cookieMatch ? decodeURIComponent(cookieMatch[0].split("=")[1]) : null;
},
setCookie: function(name, value, expires, path) {
// expires must be number of minutes or instance of Date;
if(expires === null || typeof expires == 'undefined') {
expires = '';
} else {
var date;
if (typeof expires == 'number') {
date = new Date();
date.setTime(date.getTime() + expires * 60 * 1e3);
} else {
date = expires;
}
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + escape(value) + expires + "; path=" + (path || '/');
}
};
Popunder.prototype = {
defaultWindowOptions: {
width : window.screen.width,
height : window.screen.height,
left : 0,
top : 0,
location : 1,
toolbar : 1,
status : 1,
menubar : 1,
scrollbars : 1,
resizable : 1
},
defaultPopOptions: {
cookieExpires : 60, // in minutes
cookiePath : '/',
newTab : true,
blur : true,
blurByAlert : false, //
chromeDelay : 500,
smart : false, // for feature, if browsers block event click to window/body
beforeOpen : function(){},
afterOpen : function(){}
},
// Must use the options to create a new window in chrome
__chromeNewWindowOptions: {
scrollbars : 0
},
__construct: function(url, options) {
this.url = url;
this.index = counter++;
this.name = baseName + '_' + (this.index);
this.executed = false;
this.setOptions(options);
this.register();
},
register: function() {
//if (this.isExecuted()) return;
var self = this, w, i,
elements = [],
eventName = 'click',
run = function(e) {
// e.preventDefault();
//if (self.shouldExecute()) {
lastPopTime = new Date().getTime();
self.setExecuted();
self.options.beforeOpen.call(undefined, this);
if (self.options.newTab) {
if (browser.chrome && browser.version > 30 && self.options.blur) {
window.open('javascript:window.focus()', '_self', '');
helper.simulateClick(self.url);
w = null;
} else {
w = parent.window.open(self.url, '_blank');
setTimeout(function(){
if (!alertCalled && self.options.blurByAlert) {
alertCalled = true;
alert();
}
}, 3);
}
} else {
w = parent.window.open(self.url, this.url, self.getParams());
}
if (self.options.blur) {
helper.blur(w);
}
self.options.afterOpen.call(undefined, this);
for(i in elements) {
helper.detachEvent(eventName, run, elements[i]);
}
//}
},
inject = function(e){
if (self.isExecuted()) {
helper.detachEvent('mousemove', inject);
return;
}
try {
if (e.originalTarget && typeof e.originalTarget[self.name] == 'undefined') {
e.originalTarget[self.name] = true;
helper.attachEvent(eventName, run, e.originalTarget);
elements.push(e.originalTarget);
}
} catch(err) {}
};
// smart injection
if (this.options.smart) {
helper.attachEvent('mousemove', inject);
} else {
helper.attachEvent(eventName, run, window);
elements.push(window);
helper.attachEvent(eventName, run, document);
elements.push(document);
}
},
shouldExecute: function() {
if (browser.chrome && lastPopTime && lastPopTime + this.options.chromeDelay > new Date().getTime()) {
return false;
}
return !this.isExecuted();
},
isExecuted: function() {
return this.executed || !!helper.getCookie(this.name);
},
setExecuted: function() {
this.executed = true;
helper.setCookie(this.name, 1, this.options.cookieExpires, this.options.cookiePath);
},
setOptions: function(options) {
this.options = helper.mergeObject(this.defaultWindowOptions, this.defaultPopOptions, options || {});
if (!this.options.newTab && browser.chrome) {
for(var k in this.__chromeNewWindowOptions) {
this.options[k] = this.__chromeNewWindowOptions[k];
}
}
},
getParams: function() {
var params = '', k;
for (k in this.options) {
if (typeof this.defaultWindowOptions[k] != 'undefined') {
params += (params ? "," : "") + k + "=" + this.options[k];
}
}
return params;
}
};
Popunder.make = function(url, options) {
return new this(url, options);
};
window.SmartPopunder = Popunder;
})(window);
I've tried in different ways to solve this but it won't work, what I need to mention is that, I'm a noob in javascript
THANKS FOR NO HELP; I miss the old times when users went here for help even if they were a noob, they would still get some help, nowadays all you get is "Suggested Editing" they fix you and "I" and nothing much, what if English is not my first language? FFS what happened to this community?
Anyways, maybe there will be noob people like me that will want to use this popunder, i fixed the problem here is the full working code.
/**
* Smart Popunder maker.
* This class provides an easy way to make a popunder.
* Avoid blocked on Google Chrome
*
* Note: For Google Chrome, to avoid blocked so each popunder will be fired by each click.
*
* #author: Phan Thanh Cong aka chiplove <ptcong90#gmail.com>
* #license: MIT
*
* Edit by: Rafel Sansó <rafel.sanso#gmail.com>
*
* Changelog
*
* version 2.3.2.1; Apr 23, 2015
* - Eventually, the popup doesn't launch. To prevent this I comment lines 174, 180 and 208
*
*/
(function(window){
"use strict";
var Popunder = function(url, options){ this.__construct(url, options); },
counter = 0,
lastPopTime = 0,
alertCalled = false,
baseName = 'ChipPopunder',
parent = top != self ? top : self,
userAgent = navigator.userAgent.toLowerCase(),
browser = {
webkit: /webkit/.test(userAgent),
mozilla: /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent),
chrome: /chrome/.test(userAgent),
msie: /msie|trident\//.test(userAgent) && !/opera/.test(userAgent),
firefox: /firefox/.test(userAgent),
safari: /safari/.test(userAgent) && !/chrome/.test(userAgent),
opera: /opera/.test(userAgent),
version: parseInt(userAgent.match(/(?:[^\s]+(?:ri|ox|me|ra)\/|trident\/.*?rv:)([\d]+)/i)[1], 10)
},
helper = {
simulateClick: function(url) {
var a = document.createElement("a"),
nothing = "",
evt = document.createEvent("MouseEvents");
a.href = url || "data:text/html,<script>window.close();<\/script>;";
document.body.appendChild(a);
evt.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, true, false, false, true, 0, null);
a.dispatchEvent(evt);
a.parentNode.removeChild(a);
},
blur: function(popunder) {
try {
popunder.blur();
popunder.opener.window.focus();
window.self.window.focus();
window.focus();
if (browser.firefox) {
this.openCloseWindow(popunder);
} else if (browser.webkit) {
// try to blur popunder window on chrome
// but not works on chrome 41
// so we should wrap this to avoid chrome display warning
if (!browser.chrome || (browser.chrome && browser.version < 41)) {
this.openCloseTab();
}
} else if (browser.msie) {
setTimeout(function() {
popunder.blur();
popunder.opener.window.focus();
window.self.window.focus();
window.focus();
}, 1000);
}
} catch(err) {}
},
openCloseWindow: function(popunder) {
var tmp = popunder.window.open("about:blank");
tmp.focus();
tmp.close();
setTimeout(function() {
try {
tmp = popunder.window.open("about:blank");
tmp.focus();
tmp.close();
} catch (e) {}
}, 1);
},
openCloseTab: function() {
this.simulateClick();
},
detachEvent: function(event, callback, object) {
var object = object || window;
if (!object.removeEventListener) {
return object.detachEvent("on" + event, callback);
}
return object.removeEventListener(event, callback);
},
attachEvent: function(event, callback, object) {
var object = object || window;
if (!object.addEventListener) {
return object.attachEvent("on" + event, callback);
}
return object.addEventListener(event, callback);
},
mergeObject: function() {
var obj = {}, i, k;
for(i = 0; i < arguments.length; i++) {
for (k in arguments[i]) {
obj[k] = arguments[i][k];
}
}
return obj;
},
getCookie: function(name) {
var cookieMatch = document.cookie.match(new RegExp(name+"=[^;]+", "i"));
return cookieMatch ? decodeURIComponent(cookieMatch[0].split("=")[1]) : null;
},
setCookie: function(name, value, expires, path) {
// expires must be number of minutes or instance of Date;
if(expires === null || typeof expires == 'undefined') {
expires = '';
} else {
var date;
if (typeof expires == 'number') {
date = new Date();
date.setTime(date.getTime() + expires * 60 * 1e3);
} else {
date = expires;
}
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + escape(value) + expires + "; path=" + (path || '/');
}
};
Popunder.prototype = {
defaultWindowOptions: {
width : window.screen.width,
height : window.screen.height,
left : 0,
top : 0,
location : 1,
toolbar : 1,
status : 1,
menubar : 1,
scrollbars : 1,
resizable : 1
},
defaultPopOptions: {
cookieExpires : 60, // in minutes
cookiePath : '/',
newTab : true,
blur : true,
blurByAlert : false, //
chromeDelay : 500,
smart : false, // for feature, if browsers block event click to window/body
beforeOpen : function(){},
afterOpen : function(){}
},
// Must use the options to create a new window in chrome
__chromeNewWindowOptions: {
scrollbars : 0
},
__construct: function(url, options) {
this.url = url;
this.index = counter++;
this.name = baseName + '_' + (this.index);
this.executed = false;
this.setOptions(options);
this.register();
},
register: function() {
if (this.isExecuted()) return;
var self = this, w, i,
elements = [],
eventName = 'click',
run = function(e) {
// e.preventDefault();
//if (self.shouldExecute()) {
lastPopTime = new Date().getTime();
self.setExecuted();
self.options.beforeOpen.call(undefined, this);
if (self.options.newTab) {
if (browser.chrome && browser.version > 30 && self.options.blur) {
window.open('javascript:window.focus()', '_self', '');
helper.simulateClick(self.url);
w = null;
} else {
w = parent.window.open(self.url, '_blank');
setTimeout(function(){
if (!alertCalled && self.options.blurByAlert) {
alertCalled = true;
alert();
}
}, 3);
}
} else {
w = parent.window.open(self.url, this.url, self.getParams());
}
if (self.options.blur) {
helper.blur(w);
}
self.options.afterOpen.call(undefined, this);
for(i in elements) {
helper.detachEvent(eventName, run, elements[i]);
}
//}
},
inject = function(e){
if (self.isExecuted()) {
helper.detachEvent('mousemove', inject);
return;
}
try {
if (e.originalTarget && typeof e.originalTarget[self.name] == 'undefined') {
e.originalTarget[self.name] = true;
helper.attachEvent(eventName, run, e.originalTarget);
elements.push(e.originalTarget);
}
} catch(err) {}
};
// smart injection
if (this.options.smart) {
helper.attachEvent('mousemove', inject);
} else {
helper.attachEvent(eventName, run, window);
elements.push(window);
helper.attachEvent(eventName, run, document);
elements.push(document);
}
},
shouldExecute: function() {
if (browser.chrome && lastPopTime && lastPopTime + this.options.chromeDelay > new Date().getTime()) {
return false;
}
return !this.isExecuted();
},
isExecuted: function() {
return this.executed || !!helper.getCookie(this.name);
},
setExecuted: function() {
this.executed = true;
helper.setCookie(this.name, 1, this.options.cookieExpires, this.options.cookiePath);
},
setOptions: function(options) {
this.options = helper.mergeObject(this.defaultWindowOptions, this.defaultPopOptions, options || {});
if (!this.options.newTab && browser.chrome) {
for(var k in this.__chromeNewWindowOptions) {
this.options[k] = this.__chromeNewWindowOptions[k];
}
}
},
getParams: function() {
var params = '', k;
for (k in this.options) {
if (typeof this.defaultWindowOptions[k] != 'undefined') {
params += (params ? "," : "") + k + "=" + this.options[k];
}
}
return params;
}
};
Popunder.make = function(url, options) {
return new this(url, options);
};
window.SmartPopunder = Popunder;
})(window);
add the code above into a js file like popunder.js and in order to trigger it you will need to use this code
<script type="text/javascript" src="https://www.website.com/js/popunder.js"></script>
<script type="text/javascript">
// use cookie expires on 1 hour * cookieExpires
SmartPopunder.make('https://www.website.com', {cookieExpires:60, newTab: true, width: window.screen.width, height: window.screen.height});
</script>
Regards
I am using a plugin for live search .. everything is working fine .. i just want to add a loading png that appear on start of ajax request and disappear on results ..
please help me to customize the code just to add class where form id="search-kb-form" .. and remove the class when results are completed.
<form id="search-kb-form" class="search-kb-form" method="get" action="<?php echo home_url('/'); ?>" autocomplete="off">
<div class="wrapper-kb-fields">
<input type="text" id="s" name="s" placeholder="Search what you’re looking for" title="* Please enter a search term!">
<input type="submit" class="submit-button-kb" value="">
</div>
<div id="search-error-container"></div>
</form>
This is the plugin code
jQuery.fn.liveSearch = function (conf) {
var config = jQuery.extend({
url: {'jquery-live-search-result': 'search-results.php?q='},
id: 'jquery-live-search',
duration: 400,
typeDelay: 200,
loadingClass: 'loading',
onSlideUp: function () {},
uptadePosition: false,
minLength: 0,
width: null
}, conf);
if (typeof(config.url) == "string") {
config.url = { 'jquery-live-search-result': config.url }
} else if (typeof(config.url) == "object") {
if (typeof(config.url.length) == "number") {
var urls = {}
for (var i = 0; i < config.url.length; i++) {
urls['jquery-live-search-result-' + i] = config.url[i];
}
config.url = urls;
}
}
var searchStatus = {};
var liveSearch = jQuery('#' + config.id);
var loadingRequestCounter = 0;
// Create live-search if it doesn't exist
if (!liveSearch.length) {
liveSearch = jQuery('<div id="' + config.id + '"></div>')
.appendTo(document.body)
.hide()
.slideUp(0);
for (key in config.url) {
liveSearch.append('<div id="' + key + '"></div>');
searchStatus[key] = false;
}
// Close live-search when clicking outside it
jQuery(document.body).click(function(event) {
var clicked = jQuery(event.target);
if (!(clicked.is('#' + config.id) || clicked.parents('#' + config.id).length || clicked.is('input'))) {
liveSearch.slideUp(config.duration, function () {
config.onSlideUp();
});
}
});
}
return this.each(function () {
var input = jQuery(this).attr('autocomplete', 'off');
var liveSearchPaddingBorderHoriz = parseInt(liveSearch.css('paddingLeft'), 10) + parseInt(liveSearch.css('paddingRight'), 10) + parseInt(liveSearch.css('borderLeftWidth'), 10) + parseInt(liveSearch.css('borderRightWidth'), 10);
// Re calculates live search's position
var repositionLiveSearch = function () {
var tmpOffset = input.offset();
var tmpWidth = input.outerWidth();
if (config.width != null) {
tmpWidth = config.width;
}
var inputDim = {
left: tmpOffset.left,
top: tmpOffset.top,
width: tmpWidth,
height: input.outerHeight()
};
inputDim.topPos = inputDim.top + inputDim.height;
inputDim.totalWidth = inputDim.width - liveSearchPaddingBorderHoriz;
liveSearch.css({
position: 'absolute',
left: inputDim.left + 'px',
top: inputDim.topPos + 'px',
width: inputDim.totalWidth + 'px'
});
};
var showOrHideLiveSearch = function () {
if (loadingRequestCounter == 0) {
showStatus = false;
for (key in config.url) {
if( searchStatus[key] == true ) {
showStatus = true;
break;
}
}
if (showStatus == true) {
for (key in config.url) {
if( searchStatus[key] == false ) {
liveSearch.find('#' + key).html('');
}
}
showLiveSearch();
} else {
hideLiveSearch();
}
}
};
// Shows live-search for this input
var showLiveSearch = function () {
// Always reposition the live-search every time it is shown
// in case user has resized browser-window or zoomed in or whatever
repositionLiveSearch();
// We need to bind a resize-event every time live search is shown
// so it resizes based on the correct input element
jQuery(window).unbind('resize', repositionLiveSearch);
jQuery(window).bind('resize', repositionLiveSearch);
liveSearch.slideDown(config.duration)
};
// Hides live-search for this input
var hideLiveSearch = function () {
liveSearch.slideUp(config.duration, function () {
config.onSlideUp();
for (key in config.url) {
liveSearch.find('#' + key).html('');
}
});
};
input
// On focus, if the live-search is empty, perform an new search
// If not, just slide it down. Only do this if there's something in the input
.focus(function () {
if (this.value.length > config.minLength ) {
showOrHideLiveSearch();
}
})
// Auto update live-search onkeyup
.keyup(function () {
// Don't update live-search if it's got the same value as last time
if (this.value != this.lastValue) {
input.addClass(config.loadingClass);
var q = this.value;
// Stop previous ajax-request
if (this.timer) {
clearTimeout(this.timer);
}
if( q.length > config.minLength ) {
// Start a new ajax-request in X ms
this.timer = setTimeout(function () {
for (url_key in config.url) {
loadingRequestCounter += 1;
jQuery.ajax({
key: url_key,
url: config.url[url_key] + q,
success: function(data){
if (data.length) {
searchStatus[this.key] = true;
liveSearch.find("#" + this.key).html(data);
} else {
searchStatus[this.key] = false;
}
loadingRequestCounter -= 1;
showOrHideLiveSearch();
}
});
}
}, config.typeDelay);
}
else {
for (url_key in config.url) {
searchStatus[url_key] = false;
}
hideLiveSearch();
}
this.lastValue = this.value;
}
});
});
};
add a background to the loading class
.loading {
background:url('http://path_to_your_picture');
}
I'm using a Youtube-TV JS plugin for a client site (https://github.com/Giorgio003/Youtube-TV ). The player loads with a playlist in an open state, and I need to have it load with the toggle closed, showing the array of playlists, can anyone help?
my codepen for the player is here
http://codepen.io/raldesign/pen/OVYXvK
(function(win, doc) {
'use strict';
var apiKey = 'AIzaSyAFMzeux_Eu933wk5U8skMzUzA-urgVgsY';
var YTV = YTV || function(id, opts){
var noop = function(){},
settings = {
apiKey: apiKey,
element: null,
user: null,
channelId: null,
fullscreen: false,
accent: '#fff',
controls: true,
annotations: false,
autoplay: false,
chainVideos: true,
browsePlaylists: false,
playerTheme: 'dark',
listTheme: 'dark',
responsive: false,
playId:'',
sortList: false,
reverseList: false,
shuffleList: false,
wmode: 'opaque',
events: {
videoReady: noop,
stateChange: noop
}
},
cache = {
data: {},
remove: function (url) {
delete cache.data[url];
},
exist: function (url) {
return cache.data.hasOwnProperty(url) && cache.data[url] !== null;
},
get: function (url) {
return cache.data[url];
},
set: function (url, data) {
cache.remove(url);
cache.data[url] = data;
}
},
utils = {
events: {
addEvent: function addEvent(element, eventName, func) {
if (element.addEventListener) {
return element.addEventListener(eventName, func, false);
} else if (element.attachEvent) {
return element.attachEvent("on" + eventName, func);
}
},
removeEvent: function addEvent(element, eventName, func) {
if (element.addEventListener) {
return element.removeEventListener(eventName, func, false);
} else if (element.attachEvent) {
return element.detachEvent("on" + eventName, func);
}
},
prevent: function(e) {
if (e.preventDefault) {
e.preventDefault();
} else {
e.returnValue = false;
}
}
},
addCSS: function(css){
var head = doc.getElementsByTagName('head')[0],
style = doc.createElement('style');
style.type = 'text/css';
if (style.styleSheet){
style.styleSheet.cssText = css;
} else {
style.appendChild(doc.createTextNode(css));
}
head.appendChild(style);
},
addCommas: function(str){
var x = str.split('.'),
x1 = x[0],
x2 = x.length > 1 ? '.' + x[1] : '',
rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
},
parentUntil: function(el, attr) {
while (el.parentNode) {
if (el.getAttribute && el.getAttribute(attr)){
return el;
}
el = el.parentNode;
}
return null;
},
ajax: {
get: function(url, fn){
if (cache.exist(url)) {
fn.call(this, JSON.parse(cache.get(url)));
} else {
var handle;
if (win.XDomainRequest && !(navigator.appVersion.indexOf("MSIE 8")==-1 || navigator.appVersion.indexOf("MSIE 9")==-1)) { // CORS for IE8,9
handle = new XDomainRequest();
handle.onload = function(){
cache.set(url, handle.responseText);
fn.call(this, JSON.parse(handle.responseText));
if (Object.prototype.hasOwnProperty.call(JSON.parse(handle.responseText), 'error')){
cache.remove(url);
var e = JSON.parse(handle.responseText);
console.log('Youtube-TV Error: Youtube API Response: '+e.error.errors[0].reason+'\n'+ 'Details: '+e.error.errors[0].message);
}
};
} else if (win.XMLHttpRequest){ // Modern Browsers
handle = new XMLHttpRequest();
}
handle.onreadystatechange = function(){
if (handle.readyState === 4 && handle.status === 200){
cache.set(url, handle.responseText);
fn.call(this, JSON.parse(handle.responseText));
} else if (handle.readyState === 4){
var e = JSON.parse(handle.responseText);
console.log('Youtube-TV Error: Youtube API Response: '+e.error.errors[0].reason+'\n'+ 'Details: '+e.error.errors[0].message);
}
};
handle.open("GET",url,true);
handle.send();
}
}
},
endpoints: {
base: 'https://www.googleapis.com/youtube/v3/',
userInfo: function(){
return utils.endpoints.base+'channels?'+settings.cid+'&key='+apiKey+'&part=snippet,contentDetails,statistics';
},
playlistInfo: function(pid){
return utils.endpoints.base+'playlists?id='+pid+'&key='+apiKey+'&maxResults=50&part=snippet';
},
userPlaylists: function(){
return utils.endpoints.base+'playlists?channelId='+settings.channelId+'&key='+apiKey+'&maxResults=50&part=snippet';
},
playlistVids: function(){
return utils.endpoints.base+'playlistItems?playlistId='+settings.pid+'&key='+apiKey+'&maxResults=50&part=contentDetails';
},
videoInfo: function(){
return utils.endpoints.base+'videos?id='+settings.videoString+'&key='+apiKey+'&maxResults=50&part=snippet,contentDetails,status,statistics';
}
},
deepExtend: function(destination, source) {
var property;
for (property in source) {
if (source[property] && source[property].constructor && source[property].constructor === Object) {
destination[property] = destination[property] || {};
utils.deepExtend(destination[property], source[property]);
} else {
destination[property] = source[property];
}
}
return destination;
}
},
prepare = {
youtube: function(){
if(typeof YT=='undefined'){
var tag = doc.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = doc.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
}
},
build: function(){
if (settings.channelId){
settings.cid = 'id='+settings.channelId;
} else if(settings.user){
settings.cid = 'forUsername='+settings.user;
}
settings.element.className = "ytv-canvas";
if(settings.fullscreen){
settings.element.className += " ytv-full";
}
utils.addCSS( '#'+id+' .ytv-list .ytv-active a{border-left-color: '+(settings.accent)+';}' );
// Responsive CSS
if(settings.responsive){
utils.addCSS('#'+id+' .ytv-video{'
+'position: relative; padding-bottom: 39.4%; /* 16:9 of 70%*/'
+'height: 0; width: 70%;'
+'} #'+id+' .ytv-video iframe{'
+'position: absolute; top: 0; left: 0;'
+'} #'+id+' .ytv-list{'
+'width: 30%;'
+'} #'+id+' .ytv-playlist-open .ytv-arrow{'
+'top: 0px;}'
+'#media only screen and (max-width:992px) {'
+'#'+id+' .ytv-list{'
+'position: relative; display: block;'
+'width: 0; padding-bottom: 40%;'
+'left: auto; right: auto;'
+'top: auto; width: 100%;'
+'} #'+id+' .ytv-video{'
+'position: relative; padding-bottom: 56.25%; /* 16:9 */'
+'height: 0; position: relative;'
+'display: block; left: auto;'
+'right: auto; top: auto; width: 100%;'
+'}}'
);
}
// Temp Scroll Bar fix
if (settings.listTheme == 'dark'){
utils.addCSS( ' #'+id+'.ytv-canvas ::-webkit-scrollbar{border-left: 1px solid #000;}'
+ ' #'+id+'.ytv-canvas ::-webkit-scrollbar-thumb{background: rgba(255,255,255,0.2);}');
}
// Optional Light List Theme
if(settings.listTheme == 'light'){
utils.addCSS( ' #'+id+'.ytv-canvas{background: #ccc;}'
+ ' #'+id+'.ytv-canvas ::-webkit-scrollbar{border-left: 1px solid rgba(28,28,28,0.1);}'
+ ' #'+id+'.ytv-canvas ::-webkit-scrollbar-thumb{background: rgba(28,28,28,0.3);}'
+ ' #'+id+' .ytv-list .ytv-active a{background: rgba(0,0,0,0.2);}'
+ ' #'+id+' .ytv-list a{color: #282828; border-top: 1px solid rgba(0,0,0,0.1); border-bottom: 1px solid rgba(204,204,204,0.5);}'
+ ' #'+id+' .ytv-list a:hover, #'+id+' .ytv-list-header .ytv-playlists a:hover{ background: rgba(0,0,0,0.2);}'
+ ' #'+id+' .ytv-list a:active, #'+id+' .ytv-list-header .ytv-playlists a:active{ background: rgba(0,0,0,0.2);}'
+ ' #'+id+' .ytv-list .ytv-thumb-stroke{outline: 1px solid rgba(0,0,0,0.1);}'
+ ' #'+id+' .ytv-list .ytv-thumb{outline: 1px solid rgba(255,255,255,0.5);}'
+ ' #'+id+' .ytv-list-header{-webkit-box-shadow: 0 1px 2px rgba(255, 255, 255, 0.2); -moz-box-shadow: 0 1px 2px rgba(255, 255, 255, 0.2); box-shadow: 0 1px 2px rgba(255, 255, 255, 0.2);}'
+ ' #'+id+' .ytv-list-header a{background: rgba(0,0,0,0.2);}'
+ ' #'+id+' .ytv-playlists{background: #ccc;}'
);
}
},
userUploads: function(userInfo){
if (userInfo && userInfo.items.length > 0){
settings.pid = userInfo.items[0].contentDetails.relatedPlaylists.uploads;
utils.ajax.get( utils.endpoints.playlistVids(), prepare.compileVideos );
} else console.log ('Youtube-TV Error: API returned no matches for: '+(settings.channelId ? settings.channelId : settings.user)+'\nPlease ensure it was entered correctly and in the appropriate field shown below. \nuser: \'username\' or channelId: \'UCxxxx...\'');
},
selectedPlaylist: function(playlistInfo){
if (playlistInfo && playlistInfo.items.length > 0) {
if (!settings.channelId && !settings.user){
settings.cid = ('id='+(settings.channelId = playlistInfo.items[0].snippet.channelId));
}
settings.currentPlaylist = playlistInfo.items[0].snippet.title;
settings.pid = playlistInfo.items[0].id;
utils.ajax.get( utils.endpoints.playlistVids(), prepare.compileVideos );
} else console.log ('Youtube-TV Error: API returned no matches for playlist(s): '+settings.playlist);
},
compileVideos: function(res){
if (res && res.items.length > 0){
var playlists = res.items,
i;
settings.videoString = '';
for(i=0; i<playlists.length; i++){
settings.videoString += playlists[i].contentDetails.videoId;
if (i<playlists.length-1){ settings.videoString += ',';}
}
utils.ajax.get( utils.endpoints.videoInfo(), prepare.compileList );
} else console.log ('Youtube-TV Error: Empty playlist');
},
playlists: function(res){
if(res && res.items.length > 0){
var list = '<div class="ytv-playlists"><ul>',
playlists = res.items,
i;
for(i=0; i<playlists.length; i++){
var data = {
title: playlists[i].snippet.title,
plid: playlists[i].id,
thumb: playlists[i].snippet.thumbnails.medium.url
};
list += '<a href="#" data-ytv-playlist="'+(data.plid)+'">';
list += '<div class="ytv-thumb"><div class="ytv-thumb-stroke"></div><img src="'+(data.thumb)+'"></div>';
list += '<span>'+(data.title)+'</span>';
list += '</a>';
}
list += '</ul></div>';
var lh = settings.element.getElementsByClassName('ytv-list-header')[0],
headerLink = lh.children[0];
headerLink.href="#";
headerLink.target="";
headerLink.setAttribute('data-ytv-playlist-toggle', 'true');
settings.element.getElementsByClassName('ytv-list-header')[0].innerHTML += list;
lh.className += ' ytv-has-playlists';
} else console.log ('Youtube-TV Error: Returned no playlists');
},
compileList: function(data){
if(data && data.items.length > 0){
utils.ajax.get( utils.endpoints.userInfo(), function(userInfo){
var list = '',
user = {
title: userInfo.items[0].snippet.title,
url: '//youtube.com/channel/'+userInfo.items[0].id,
thumb: userInfo.items[0].snippet.thumbnails['default'].url,
summary: userInfo.items[0].snippet.description,
subscribers: userInfo.items[0].statistics.subscriberCount,
views: userInfo.items[0].statistics.viewCount
},
videos = data.items,
first = true,
i;
settings.channelId = userInfo.items[0].id;
if(settings.currentPlaylist) user.title += ' · '+(settings.currentPlaylist);
if (settings.sortList) videos.sort(function(a,b){if(a.snippet.publishedAt > b.snippet.publishedAt) return -1;if(a.snippet.publishedAt < b.snippet.publishedAt) return 1;return 0;});
if (settings.reverseList) videos.reverse();
if (settings.shuffleList) {
videos = function (){for(var j, x, i = videos.length; i; j = Math.floor(Math.random() * i), x = videos[--i], videos[i] = videos[j], videos[j] = x);return videos;}();
}
list += '<div class="ytv-list-header">';
list += '<a href="'+(user.url)+'" target="_blank">';
list += '<img src="'+(user.thumb)+'">';
list += '<span><i class="ytv-arrow down"></i>'+(user.title)+'</span>';
list += '</a>';
list += '</div>';
list += '<div class="ytv-list-inner"><ul>';
for(i=0; i<videos.length; i++){
if(videos[i].status.embeddable){
var video = {
title: videos[i].snippet.title,
slug: videos[i].id,
link: 'https://www.youtube.com/watch?v='+videos[i].id,
published: videos[i].snippet.publishedAt,
stats: videos[i].statistics,
duration: (videos[i].contentDetails.duration),
thumb: videos[i].snippet.thumbnails.medium.url
};
var durationString = video.duration.match(/[0-9]+[HMS]/g);
var h = 0, m = 0, s = 0, time = '';
durationString.forEach(function (duration) {
var unit = duration.charAt(duration.length-1);
var amount = parseInt(duration.slice(0,-1));
switch (unit) {
case 'H': h = (amount > 9 ? '' + amount : '0' + amount); break;
case 'M': m = (amount > 9 ? '' + amount : '0' + amount); break;
case 'S': s = (amount > 9 ? '' + amount : '0' + amount); break;
}
});
if (h){ time += h+':';}
if (m){ time += m+':';} else { time += '00:';}
if (s){ time += s;} else { time += '00';}
var isFirst = '';
if(settings.playId==video.slug){
isFirst = ' class="ytv-active"';
first = video.slug;
} else if(first===true){
first = video.slug;
}
list += '<li'+isFirst+'><a href="#" data-ytv="'+(video.slug)+'" class="ytv-clear">';
list += '<div class="ytv-thumb"><div class="ytv-thumb-stroke"></div><span>'+(time)+'</span><img src="'+(video.thumb)+'"></div>';
list += '<div class="ytv-content"><b>'+(video.title)+'</b>';
if (video.stats)
{
list+='</b><span class="ytv-views">'+utils.addCommas(video.stats.viewCount)+' Views</span>';
}
list += '</div></a></li>';
}
}
list += '</ul></div>';
settings.element.innerHTML = '<div class="ytv-relative"><div class="ytv-video"><div id="ytv-video-player"></div></div><div class="ytv-list">'+list+'</div></div>';
if(settings.element.getElementsByClassName('ytv-active').length===0){
settings.element.getElementsByTagName('li')[0].className = "ytv-active";
}
var active = settings.element.getElementsByClassName('ytv-active')[0];
active.parentNode.parentNode.scrollTop = active.offsetTop;
action.logic.loadVideo(first, settings.autoplay);
if (settings.playlist){
utils.ajax.get( utils.endpoints.playlistInfo(settings.playlist), prepare.playlists );
} else if(settings.browsePlaylists){
utils.ajax.get( utils.endpoints.userPlaylists(), prepare.playlists );
}
});
} else console.log ('Youtube-TV Error: Empty video list');
}
},
action = {
logic: {
playerStateChange: function(d){
console.log(d);
},
loadVideo: function(slug, autoplay){
var house = settings.element.getElementsByClassName('ytv-video')[0];
var counter = settings.element.getElementsByClassName('ytv-video-playerContainer').length;
house.innerHTML = '<div id="ytv-video-player'+id+counter+'" class="ytv-video-playerContainer"></div>';
cache.player = new YT.Player('ytv-video-player'+id+counter, {
videoId: slug,
events: {
onReady: settings.events.videoReady,
onStateChange: function(e){
if( (e.target.getPlayerState()===0) && settings.chainVideos ){
var ns = settings.element.getElementsByClassName('ytv-active')[0].nextSibling,
link = ns.children[0];
link.click();
}
settings.events.stateChange.call(this, e);
}
},
playerVars: {
enablejsapi: 1,
origin: doc.domain,
controls: settings.controls ? 1 : 0,
rel: 0,
showinfo: 0,
iv_load_policy: settings.annotations ? '' : 3,
autoplay: autoplay ? 1 : 0,
theme: settings.playerTheme,
wmode: settings.wmode
}
});
}
},
endpoints: {
videoClick: function(e){
var target = utils.parentUntil(e.target ? e.target : e.srcElement, 'data-ytv');
if(target){
if(target.getAttribute('data-ytv')){
// Load Video
utils.events.prevent(e);
var activeEls = settings.element.getElementsByClassName('ytv-active'),
i;
for(i=0; i<activeEls.length; i++){
activeEls[i].className="";
}
target.parentNode.className="ytv-active";
action.logic.loadVideo(target.getAttribute('data-ytv'), true);
}
}
},
playlistToggle: function(e){
var target = utils.parentUntil(e.target ? e.target : e.srcElement, 'data-ytv-playlist-toggle');
if(target && target.getAttribute('data-ytv-playlist-toggle')){
// Toggle Playlist
utils.events.prevent(e);
var lh = settings.element.getElementsByClassName('ytv-list-header')[0];
if(lh.className.indexOf('ytv-playlist-open')===-1){
lh.className += ' ytv-playlist-open';
} else {
lh.className = lh.className.replace(' ytv-playlist-open', '');
}
}
},
playlistClick: function(e){
var target = utils.parentUntil(e.target ? e.target : e.srcElement, 'data-ytv-playlist');
if(target && target.getAttribute('data-ytv-playlist')){
// Load Playlist
utils.events.prevent(e);
settings.pid = target.getAttribute('data-ytv-playlist');
target.children[1].innerHTML = 'Loading...';
utils.ajax.get( utils.endpoints.playlistInfo(settings.pid), function(res){
var lh = settings.element.getElementsByClassName('ytv-list-header')[0];
lh.className = lh.className.replace(' ytv-playlist-open', '');
prepare.selectedPlaylist(res);
});
}
}
},
bindEvents: function(){
utils.events.addEvent( settings.element, 'click', action.endpoints.videoClick );
utils.events.addEvent( settings.element, 'click', action.endpoints.playlistToggle );
utils.events.addEvent( settings.element, 'click', action.endpoints.playlistClick );
}
},
initialize = function(id, opts){
utils.deepExtend(settings, opts);
if(settings.apiKey.length===0){
alert("Missing APIkey in settings or as global vaiable.");
}
apiKey = settings.apiKey;
settings.element = (typeof id==='string') ? doc.getElementById(id) : id;
if(settings.element && (settings.user || settings.channelId || settings.playlist)){
prepare.youtube();
prepare.build();
action.bindEvents();
if (settings.playlist) {
utils.ajax.get( utils.endpoints.playlistInfo(settings.playlist), prepare.selectedPlaylist );
} else {
utils.ajax.get( utils.endpoints.userInfo(), prepare.userUploads );
}
} else console.log ('Youtube-TV Error: Missing either user, channelId, or playlist');
};
/* Public */
this.destroy = function(){
utils.events.removeEvent( settings.element, 'click', action.endpoints.videoClick );
utils.events.removeEvent( settings.element, 'click', action.endpoints.playlistToggle );
utils.events.removeEvent( settings.element, 'click', action.endpoints.playlistClick );
settings.element.className = '';
settings.element.innerHTML = '';
};
this.fullscreen = {
state: function(){
return (settings.element.className).indexOf('ytv-full') !== -1;
},
enter: function(){
if( (settings.element.className).indexOf('ytv-full') === -1 ){
settings.element.className += 'ytv-full';
}
},
exit: function(){
if( (settings.element.className).indexOf('ytv-full') !== -1 ){
settings.element.className = (settings.element.className).replace('ytv-full', '');
}
}
};
initialize(id, opts);
};
if ((typeof module !== 'undefined') && module.exports) {
module.exports = YTV;
}
if (typeof ender === 'undefined') {
this.YTV = YTV;
}
if ((typeof define === "function") && define.amd) {
define("YTV", [], function() {
return YTV;
});
}
if ((typeof jQuery !== 'undefined')) {
jQuery.fn.extend({
ytv: function(options) {
return this.each(function() {
new YTV(this.id, options);
});
}
});
}
}).call(this, window, document);
Replace this
list += '<div class="ytv-list-header">';
with
list += '<div class="ytv-list-header ytv-playlist-open">';
There is two playlist one is "list of all playlists". And other is "list of videos in a playlist".
"ytv-playlist-open" indicate the open status for "list of all playlist". So when it is added it will close "videos in a playlist" and show "list of all playlist" which you want to show there.
I have a plugin which re-sizes text to fit to <div>.
I have a directive which tell div inside div to change color and font-size. But, it can only change color, not font-size.
My Question is: How to override font-size of this plugin?
I couldn't import ng-fi-text plugin. So, I put it in the Javascript snippet.
The actual code is inside html.
/*! ng-fi-text v0.1.0 - 2014-11-10
* License: MIT
* Author: Leandro Bessone */
angular.module('ng-fi-text', [])
.directive('ngFiText', ['$window',
function($window) {
"use strict";
return {
restrict: 'A',
scope: {
ngFiText: '#',
ngFiTextHtml: '#'
},
link: function postLink(scope, element, attrs) {
if (!window.jQuery) {
console.error('ng-fi-text needs jQuery to work. Sory :(');
return;
}
// Options
var rotate = attrs.ngFiTextRotate || false;
var maxFontSize = attrs.ngFiTextMaxFontSize || false;
// var minFontSize = attrs.ngFiTextMinFontSize || false;
//var lineHeightMultiplier = attrs.ngFiTextLineHeightMultiplier || false;
var implementationType = attrs.hasOwnProperty('ngFiTextHtml') ? 'html' : 'text';
// Internal Options
var heightTolerance = 3;
var fontSize = 10;
var loopLimiter = 25; // higher is more accurate but increases process. Min 5~6
var executionOdometer = 0;
// Creating the element
var rotateToAdd = rotate ? ' rotate(' + rotate + 'deg) ' : '';
var textElem = angular.element('<div />').attr('style',
'word-wrap: break-word;' +
'line-height: normal;' +
'margin: 0px;' +
//'padding: 0px;'+
'position: absolute; ' +
'left:0px;' +
'right: 0px;' +
'top: 50%;' +
'-webkit-transform: translate(0%,-50%) ' + rotateToAdd + ';' +
'-moz-transform: translate(0%,-50%) ' + rotateToAdd + ';' +
'-ms-transform: translate(0%,-50%) ' + rotateToAdd + ';' +
'transform: translate(0%,-50%) ' + rotateToAdd + ';'
);
element.html(textElem);
function contentFilling(callback) {
var text = '';
if (implementationType === 'html') {
text = attrs.ngFiTextHtml || element.html() || '';
} else {
text = attrs.ngFiText || element.text() || '';
}
// Populating the DOM
textElem[implementationType](text);
if (callback)
callback();
} // contentFilling
function executeMagic() {
onStarted();
executionOdometer++;
var elementParent = textElem.parent();
var elemParentHeight = elementParent.height();
//var elemParentWidth = elementParent.width();
var elemHeight;
var heightDiff;
var baseCorrection = 10;
var definitiveCorrection;
var direction;
var prevDirection = false;
var currLoop = 1;
var currXLoop = 0;
var correctionMultiplier = 1;
var newFontSize = fontSize;
heightDiff = elemParentHeight - elemHeight;
var lastSameDirectionDiff = '',
preLastSameDirectionDiff = '';
var lesserDiff = false;
var lesserSize = false;
function grossCorrection(executionNumber) {
if (currLoop > loopLimiter) {
//console.log('no more loops :(');
//console.log('----------------------------------------- no + loops');
onFinished(newFontSize);
return;
}
onLoopStarted();
textElem.css('font-size', newFontSize + 'px');
if (implementationType === 'html') {
textElem.children().css('font-size', newFontSize + 'px');
}
window.setTimeout(function() {
if (executionNumber !== executionOdometer) {
return;
}
elemHeight = textElem.height();
heightDiff = elemParentHeight - elemHeight;
if (heightDiff >= 0 && (heightDiff < lesserDiff || !lesserDiff)) {
lesserDiff = heightDiff;
lesserSize = newFontSize;
}
direction = heightDiff >= 0 ? 1 : -1;
if (prevDirection && prevDirection !== direction) {
if (preLastSameDirectionDiff === heightDiff) {
//console.log('------------------ deberia parar -----------');
if (newFontSize !== lesserSize) {
textElem.css('font-size', lesserSize + 'px');
if (implementationType === 'html') {
textElem.children().css('font-size', lesserSize + 'px');
}
}
//console.log('----------------------------------------- dp');
onFinished(newFontSize);
return;
}
preLastSameDirectionDiff = lastSameDirectionDiff;
lastSameDirectionDiff = heightDiff;
currXLoop++;
correctionMultiplier = correctionMultiplier * (1 - 0.25 * currXLoop);
correctionMultiplier = correctionMultiplier < 0.05 ? 0.05 : correctionMultiplier;
}
prevDirection = direction;
definitiveCorrection = baseCorrection * correctionMultiplier * direction;
newFontSize = newFontSize + definitiveCorrection;
/*
console.log(
'l'+currLoop +
' | LSD:'+lastSameDirectionDiff+
' | ldif:'+lesserDiff+
' | elHght:'+elemHeight +
' | hDiff:'+heightDiff +
' | cx:'+correctionMultiplier+
' | def_corr:'+definitiveCorrection +
' | newFontSize:'+newFontSize +
'');
*/
currLoop++;
if (Math.abs(heightDiff) > heightTolerance) {
grossCorrection(executionOdometer);
} else {
//console.log('-----------------------------------------end');
onFinished(newFontSize);
}
}, 0);
} //gross
grossCorrection(executionOdometer);
} // executeMagic
function onStarted() {
textElem.css('visibility', 'hidden');
}
function onLoopStarted() {
}
function onFinished(finalFontSize) {
if (maxFontSize && finalFontSize > maxFontSize) {
textElem.css('font-size', maxFontSize + 'px');
}
textElem.css('visibility', 'visible');
}
function onResizeStarted() {
textElem.css('visibility', 'hidden');
}
// window resizing responsivenes
var timeoutHolder;
angular.element($window).bind('resize', function() {
window.clearTimeout(timeoutHolder);
onResizeStarted();
timeoutHolder = window.setTimeout(executeMagic, 150);
});
// update on values changing
scope.$watchGroup(['ngFiText', 'ngFiTextHtml'], function(newValue, oldValue) {
contentFilling(executeMagic);
});
// Staring the magic...
contentFilling(executeMagic);
}
};
}
]);
.myDiv {
width: 270px;
height: 70px;
border: solid orange;
position: absolute;
}
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://code.angularjs.org/1.4.2/angular.js"></script>
</head>
<body>
<div class='myDiv' resize-text ng-fi-text ng-fi-text-html='1234'></div>
</body>
</html>
<script>
var app = angular.module('plunker', ['ng-fi-text']);
app.directive('resizeText', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var text_len = element.text().length;
if (text_len < 15) {
element.css('font-size', '10px');
element.css('color', 'red');
}
}
}
})
</script>
Just found a solution:
element.addClass('small');
and style it:
<style>
.small > div
{
font-size: 10px !important;
}
</style>