Phantomjs doesn't render footers with a custom styles - css

I have the following example:
var page = require('webpage').create(),
system = require('system');
if (system.args.length < 3) {
console.log('Usage: printheaderfooter.js URL filename');
phantom.exit(1);
} else {
var address = system.args[1];
var output = system.args[2];
page.viewportSize = { width: 600, height: 600 };
page.paperSize = {
format: 'A4',
margin: "1cm"
footer: {
height: "1cm",
contents: phantom.callback(function(pageNum, numPages) {
if (pageNum == numPages) {
return "";
}
return "<h1 class='footer_style'>Footer" + pageNum + " / " + numPages + "</h1>";
})
}
};
page.open(address, function (status) {
if (status !== 'success') {
console.log('Unable to load the address!');
} else {
window.setTimeout(function () {
page.render(output);
phantom.exit();
}, 200);
}
});
}
In the example above I use footer_style class that look likes in my css file the following:
.footer_style {
text-align:right;
}
But unfortunately that dosen't works. I'm trying to create pdf file such as follows:
./phantomjs rasterize.js index.html test.pdf

We know that classes do not work but inline styles do. What we can do is replace the class with the computed style.
Here is a function that will take a piece of html, create a temporary element in the body with the html, compute the style for each element with a class, add the computed style inline and return the new html.
function replaceClassWithStyle(html) {
return page.evaluate(function(html) {
var host = document.createElement('div');
host.innerHTML = html;
document.body.appendChild(host); // if not appended, values will be blank
var elements = host.getElementsByTagName('*');
for (var i in elements) {
if (elements[i].className) {
elements[i].setAttribute('style', window.getComputedStyle(elements[i], null).cssText);
}
}
document.body.removeChild(host);
return host.innerHTML;
}, html);
}
Then simply call this function in your footer:
page.paperSize = {
footer: {
contents: phantom.callback(function(pageNum, numPages) {
if (pageNum == numPages) {
return "";
}
return replaceClassWithStyle("<h1 class='footer_style'>Footer" + pageNum + " / " + numPages + "</h1>");
})
}
};
You will need to move all this inside page.open().
I tested it and the footer is aligned to the right.

I have an update to mak's excellent answer for PhantomJS 1.9.7.
This version fixes:
Circumvent bug which 'blank's the parent document (PhantomJS 1.9.7)
Style mixups when styles are nested (do depth-first traversal instead)
Also works when tags do not have classes
/**
* Place HTML in the parent document, convert CSS styles to fixed computed style declarations, and return HTML.
* (required for headers/footers, which exist outside of the HTML document, and have trouble getting styling otherwise)
*/
function replaceCssWithComputedStyle(html) {
return page.evaluate(function(html) {
var host = document.createElement('div');
host.setAttribute('style', 'display:none;'); // Silly hack, or PhantomJS will 'blank' the main document for some reason
host.innerHTML = html;
// Append to get styling of parent page
document.body.appendChild(host);
var elements = host.getElementsByTagName('*');
// Iterate in reverse order (depth first) so that styles do not impact eachother
for (var i = elements.length - 1; i >= 0; i--) {
elements[i].setAttribute('style', window.getComputedStyle(elements[i], null).cssText);
}
// Remove from parent page again, so we're clean
document.body.removeChild(host);
return host.innerHTML;
}, html);
}

From my past experience, phantomjs does not support styles in custom header/footer.
The only solution that I found is to apply an inline style like this :
var page = require('webpage').create(),
system = require('system');
if (system.args.length < 3) {
console.log('Usage: printheaderfooter.js URL filename');
phantom.exit(1);
} else {
var address = system.args[1];
var output = system.args[2];
page.viewportSize = { width: 600, height: 600 };
page.paperSize = {
format: 'A4',
margin: "1cm",
footer: {
height: "1cm",
contents: phantom.callback(function(pageNum, numPages) {
return "<h1 style='text-align:right'>Footer" + pageNum + " / " + numPages + "</h1>";
})
}
};
page.open(address, function (status) {
if (status !== 'success') {
console.log('Unable to load the address!');
} else {
window.setTimeout(function () {
page.render(output);
phantom.exit();
}, 200);
}
});
}
Note : A comma is missing in your code after margin: "1cm"

Related

Apply CSS Filters to cropped image and save/upload

I can already, input the image and crop it. I tried to apply CSS filters to it, but seems the CSS filters only apply on the img tag, not the actual image.
I am using both #Alyle-cropping and ngx-image-cropper(tests). Both give to me a base64 string for the cropped image. I am able to load the cropped image to the img tag and also upload it to the database.
onCropped(e: ImgCropperEvent) {
this.croppedImage = e.dataURL;
// console.log('cropped img: ', e.dataURL);
}
onloaded(e: ImgCropperEvent) {
this.imagemOriginal = e.originalDataURL;
this.cropper.center();
console.log('img loaded', e.name);
}
onerror(e: ImgCropperErrorEvent) {
console.warn(`'${e.name}' is not a valid image`, e);
}
// Aplicar Filtros /////////////////////////////////////////////////
change(crop: Crop): void {
this.stylus = crop.nome;
this.crops.forEach(function (value) {
(value.nome === crop.nome) ? value.ehSelec = true : value.ehSelec = false;
});
// const canvas = document.getElementById('cropping'), image = document.createElement('img');
// image.src = canvas.toDataURL('image/jpeg', 1.0);
// document.body.appendChild(image);
}
enviarParanue(): void {
const ref = firebase.storage().ref(`imagens/usuarios/idTeste`).child(`nomeTeste`);
const stringa = this.removerString(this.croppedImage);
ref.put(this.base64toBlob(stringa, 'image/png')).then((snapshot) => {
// console.log('snapshot', snapshot.valueOf());
ref.getDownloadURL().then(function(downloadURL) {
console.log('File available at', downloadURL);
});
});
// ref.putString(stringa, 'base64', {contentType: 'image/png'}).then((snapshot) => {
// // console.log('snapshot', snapshot.valueOf());
// ref.getDownloadURL().then(function(downloadURL) {
// console.log('File available at', downloadURL);
// });
// });
}
removerString(stringa: string): string {
return stringa.substring(23);
}
base64toBlob(base64Data: any, contentType: any) {
contentType = contentType || '';
const sliceSize = 1024;
const byteCharacters = atob(base64Data);
const bytesLength = byteCharacters.length;
const slicesCount = Math.ceil(bytesLength / sliceSize);
const byteArrays = new Array(slicesCount);
for (let sliceIndex = 0; sliceIndex < slicesCount; ++ sliceIndex) {
const begin = sliceIndex * sliceSize;
const end = Math.min(begin + sliceSize, bytesLength);
const bytes = new Array(end - begin);
for (let offset = begin, i = 0 ; offset < end; ++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0);
}
byteArrays[sliceIndex] = new Uint8Array(bytes);
}
return new Blob(byteArrays, { type: contentType });
}
EXAMPLE OF THE CSS FILTERS:
.none {filter:none;}
.blur {filter:blur(2.5px);}
.brightness {filter:brightness(200%);}
.contrast {filter:contrast(200%);}
.drop-shadow {filter:drop-shadow(8px 8px 10px gray);}
.grayscale {filter:grayscale(100%);}
.hue-rotate {filter:hue-rotate(90deg);}
.invert {filter:invert(100%);}
.opacity {filter:opacity(30%);}
.saturate {filter:saturate(8);}
.sepia {filter:sepia(100%);}
.contrast-brightness {filter:contrast(200%) brightness(150%);}
Problem is... I don't know how to apply the CSS filters to the image to upload the cropped with the effects(sepia, contrast, etc).
I tried to get the img src and convert it to Blob, but didn't work.
I ended up saving in the database a string with the name of the filter. So I apply the filter when I load the image. A good side of it, is that I can change the filter whenever I want.

Scrolling only side menu div and others should be fixed when menu is open

I have a side menu and when it's open, the body can be partially seen. My side menu might be long so you could scroll on it. But when the menu is at the bottom you then scroll on the body, and I don't want this behaviour.
Similar to Scrolling only content div, others should be fixed but I'm using React. Other content should be scrollable when my side menu is closed. Think of the content as side menu in the example in the link. So far I'm using the same technique provided by that answer but it's ugly (kinda jQuery):
preventOverflow = (menuOpen) => { // this is called when side menu is toggled
const body = document.getElementsByTagName('body')[0]; // this should be fixed when side menu is open
if (menuOpen) {
body.className += ' overflow-hidden';
} else {
body.className = body.className.replace(' overflow-hidden', '');
}
}
// css
.overflow-hidden {
overflow-y: hidden;
}
What should I do with Reactjs?
You should make a meta component in react to change things on the body as well as changing things like document title and things like that. I made one a while ago to do that for me. I'll add it here.
Usage
render() {
return (
<div>
<DocumentMeta bodyClasses={[isMenuOpen ? 'no-scroll' : '']} />
... rest of your normal code
</div>
)
}
DocumentMeta.jsx
import React from 'react';
import _ from 'lodash';
import withSideEffect from 'react-side-effect';
var HEADER_ATTRIBUTE = "data-react-header";
var TAG_NAMES = {
META: "meta",
LINK: "link",
};
var TAG_PROPERTIES = {
NAME: "name",
CHARSET: "charset",
HTTPEQUIV: "http-equiv",
REL: "rel",
HREF: "href",
PROPERTY: "property",
CONTENT: "content"
};
var getInnermostProperty = (propsList, property) => {
return _.result(_.find(propsList.reverse(), property), property);
};
var getTitleFromPropsList = (propsList) => {
var innermostTitle = getInnermostProperty(propsList, "title");
var innermostTemplate = getInnermostProperty(propsList, "titleTemplate");
if (innermostTemplate && innermostTitle) {
return innermostTemplate.replace(/\%s/g, innermostTitle);
}
return innermostTitle || "";
};
var getBodyIdFromPropsList = (propsList) => {
var bodyId = getInnermostProperty(propsList, "bodyId");
return bodyId;
};
var getBodyClassesFromPropsList = (propsList) => {
return propsList
.filter(props => props.bodyClasses && Array.isArray(props.bodyClasses))
.map(props => props.bodyClasses)
.reduce((classes, list) => classes.concat(list), []);
};
var getTagsFromPropsList = (tagName, uniqueTagIds, propsList) => {
// Calculate list of tags, giving priority innermost component (end of the propslist)
var approvedSeenTags = {};
var validTags = _.keys(TAG_PROPERTIES).map(key => TAG_PROPERTIES[key]);
var tagList = propsList
.filter(props => props[tagName] !== undefined)
.map(props => props[tagName])
.reverse()
.reduce((approvedTags, instanceTags) => {
var instanceSeenTags = {};
instanceTags.filter(tag => {
for(var attributeKey in tag) {
var value = tag[attributeKey].toLowerCase();
var attributeKey = attributeKey.toLowerCase();
if (validTags.indexOf(attributeKey) == -1) {
return false;
}
if (!approvedSeenTags[attributeKey]) {
approvedSeenTags[attributeKey] = [];
}
if (!instanceSeenTags[attributeKey]) {
instanceSeenTags[attributeKey] = [];
}
if (!_.has(approvedSeenTags[attributeKey], value)) {
instanceSeenTags[attributeKey].push(value);
return true;
}
return false;
}
})
.reverse()
.forEach(tag => approvedTags.push(tag));
// Update seen tags with tags from this instance
_.keys(instanceSeenTags).forEach((attr) => {
approvedSeenTags[attr] = _.union(approvedSeenTags[attr], instanceSeenTags[attr])
});
instanceSeenTags = {};
return approvedTags;
}, []);
return tagList;
};
var updateTitle = title => {
document.title = title || document.title;
};
var updateBodyId = (id) => {
document.body.setAttribute("id", id);
};
var updateBodyClasses = classes => {
document.body.className = "";
classes.forEach(cl => {
if(!cl || cl == "") return;
document.body.classList.add(cl);
});
};
var updateTags = (type, tags) => {
var headElement = document.head || document.querySelector("head");
var existingTags = headElement.querySelectorAll(`${type}[${HEADER_ATTRIBUTE}]`);
existingTags = Array.prototype.slice.call(existingTags);
// Remove any duplicate tags
existingTags.forEach(tag => tag.parentNode.removeChild(tag));
if (tags && tags.length) {
tags.forEach(tag => {
var newElement = document.createElement(type);
for (var attribute in tag) {
if (tag.hasOwnProperty(attribute)) {
newElement.setAttribute(attribute, tag[attribute]);
}
}
newElement.setAttribute(HEADER_ATTRIBUTE, "true");
headElement.insertBefore(newElement, headElement.firstChild);
});
}
};
var generateTagsAsString = (type, tags) => {
var html = tags.map(tag => {
var attributeHtml = Object.keys(tag)
.map((attribute) => {
const encodedValue = HTMLEntities.encode(tag[attribute], {
useNamedReferences: true
});
return `${attribute}="${encodedValue}"`;
})
.join(" ");
return `<${type} ${attributeHtml} ${HEADER_ATTRIBUTE}="true" />`;
});
return html.join("\n");
};
var reducePropsToState = (propsList) => ({
title: getTitleFromPropsList(propsList),
metaTags: getTagsFromPropsList(TAG_NAMES.META, [TAG_PROPERTIES.NAME, TAG_PROPERTIES.CHARSET, TAG_PROPERTIES.HTTPEQUIV, TAG_PROPERTIES.CONTENT], propsList),
linkTags: getTagsFromPropsList(TAG_NAMES.LINK, [TAG_PROPERTIES.REL, TAG_PROPERTIES.HREF], propsList),
bodyId: getBodyIdFromPropsList(propsList),
bodyClasses: getBodyClassesFromPropsList(propsList),
});
var handleClientStateChange = ({title, metaTags, linkTags, bodyId, bodyClasses}) => {
updateTitle(title);
updateTags(TAG_NAMES.LINK, linkTags);
updateTags(TAG_NAMES.META, metaTags);
updateBodyId(bodyId);
updateBodyClasses(bodyClasses)
};
var mapStateOnServer = ({title, metaTags, linkTags}) => ({
title: HTMLEntities.encode(title),
meta: generateTagsAsString(TAG_NAMES.META, metaTags),
link: generateTagsAsString(TAG_NAMES.LINK, linkTags)
});
var DocumentMeta = React.createClass({
propTypes: {
title: React.PropTypes.string,
titleTemplate: React.PropTypes.string,
meta: React.PropTypes.arrayOf(React.PropTypes.object),
link: React.PropTypes.arrayOf(React.PropTypes.object),
children: React.PropTypes.oneOfType([
React.PropTypes.object,
React.PropTypes.array
]),
bodyClasses: React.PropTypes.array,
},
render() {
if (Object.is(React.Children.count(this.props.children), 1)) {
return React.Children.only(this.props.children);
} else if (React.Children.count(this.props.children) > 1) {
return (
<span>
{this.props.children}
</span>
);
}
return null;
},
});
DocumentMeta = withSideEffect(reducePropsToState, handleClientStateChange, mapStateOnServer)(DocumentMeta);
module.exports = DocumentMeta;
This component could probably be changed a little for your case (withSideEffect is used for both client and server side rendering... if you arent using server side rendering then its probably not completely necessary) but the component will work on client side rendering if you would like to use it there as well.
ReactJS doesn't have direct access to the <body> element, and that's the element that needs to have its overflow-y style changed. So while what you're doing isn't perhaps the prettiest code, it's not entirely wrong either.
The only real suggestion I'd give is (shudder) using inline styles on the body instead of a classname so as to avoid having to introduce the CSS declaration. As long as your menu is the only thing responsible for updating the overflow-y attribute, there's no reason you can't use an inline style on it. Mashing that down with the ?: operator results in fairly simple code:
body.style.overflowY = menuOpen ? "hidden" : "";
And then you can just delete the .overflow-hidden class in its entirety.
If for some reason multiple things are managing the overflow state of the body, you might want to stick with classnames and assign a unique one for each thing managing it, something like this:
if (menuOpen) {
body.className += ' menu-open';
}
else {
// Use some tricks from jQuery to remove the "menu-open" class more elegantly.
var className = " " + body.className + " ";
className = className.replace(" overflow-hidden ", " ").replace(/\s+/, " ");
className = className.substr(1, className.length - 2);
}
CSS:
body.menu-open {
overflow-y: hidden;
}

Infinite scrolling with Meteor

I am trying to load 12 items only each time, until the user scroll all the way down and load another 12 elements
For some reason my code doesn't work. When i upload another item, i can see it in the admin panel so it is successfully uploaded but i can't see it in the normal user view. i can only view the first 12 items uploaded and it doesn't load anymore items when i scroll.
Here is my code in the client side
if (Meteor.isClient) {
var ITEMS_INCREMENT = 12; //this one refers to the number of elements to load
Session.setDefault('itemsLimit', ITEMS_INCREMENT);
Deps.autorun(function() {
Meteor.subscribe('items', Session.get('itemsLimit'));
});
Template.list_products.helpers({
applications: function () {
var limit = Session.get("itemsLimit");
//return Products.find({}, { sort: {createdAt: -1},limit: limit }); // render latest first
return Products.find({}, { sort: {createdAt: 1},limit: limit }); // render first first
}
});
Template.list_products.moreResults = function() {
// If, once the subscription is ready, we have less rows than we
// asked for, we've got all the rows in the collection.
return Products.find({}, { sort: {createdAt: -1},limit: limit });
}
// whenever #showMoreResults becomes visible, retrieve more results
function showMoreVisible() {
var threshold, target = $("#showMoreResults");
if (!target.length) return;
threshold = $(window).scrollTop() + $(window).height() - target.height();
if (target.offset().top < threshold) {
if (!target.data("visible")) {
// console.log("target became visible (inside viewable area)");
target.data("visible", true);
Session.set("itemsLimit",
Session.get("itemsLimit") + ITEMS_INCREMENT);
}
} else {
if (target.data("visible")) {
// console.log("target became invisible (below viewable arae)");
target.data("visible", false);
}
}
}
// The below line is to run the above func every time the user scrolls
$(window).scroll(showMoreVisible);
}
Here how i solved it:
if(Meteor.isClient) {
Session.set("itemsLimit", 9); // to set the limit to 9
lastScrollTop = 0;
$(window).scroll(function(event){
if($(window).scrollTop() + $(window).height() > $(document).height() - 100) { // to detect scroll event
var scrollTop = $(this).scrollTop();
if(scrollTop > lastScrollTop){ // detect scroll down
Session.set("itemsLimit", Session.get("itemsLimit") + 9); // when it reaches the end, add another 9 elements
}
lastScrollTop = scrollTop;
}
});
}
It works like a charm now :)
You can implement it like this:
HTML File:
<template name="yourTemplateName">
<div id="divId">
{{#each dataArr}}
//your view here.
{{/each}}
</div>
{{#if noMoreItem}}
<span>No more items to show</span>
{{/if}}
</template>
JS File:
var pageNumber = new ReactiveVar(0);
var noMoreItem = new ReactiveVar(false);
var mainContainer = // Your element here example: document.getElementById('divId')
mainContainer.addEventListener('scroll', function(){
if(mainContainer.scrollHeight - mainContainer.scrollTop === mainContainer.clientHeight) {
getMoreItems();
}
});
var getMoreItems = function () {
if(pageNumber.get() < Math.floor(Counts.get('countItems')/12)) {
pageNumber.set(Number(pageNumber.get())+1);
Meteor.subscribe('pubName', pageNumber.get(), 12);
} else {
noMoreItem.set(true);
}
}
Template.yourTemplateName.rendered = function () {
pageNumber.set(0);
Meteor.subscribe('pubName', pageNumber.get(), 12);
}
Template.yourTemplateName.helpers({
'dataArr': function () {
return CollectionName.find();
},
'noMoreItem': function () {
return noMoreItem.get();
}
})
Publication:
Meteor.publish("pubName", function (pageNumber, pageSize) {
Counts.publish(this, 'countItems', Meteor.users.find(filter), {
noReady: true
});
return CollectionName.find({}, {
skip: pageNumber > 0 ? ((pageNumber) * pageSize) : 0,
limit: pageSize
})
});

Joomla template issues

I'm working on a website for a school project, I'm using a template called quantua. If you go to live demo of the template ( http://www.templatesjoomla.net/index.php/joomla3-x/244-quantua-joomla-3-x.html ), you can see that when resizing the browser window the image shrinks so much that a black background appears. I don't want it to do that, how can the resizing be achived like on this (http://www.websitetemplatesonline.com/free-template/progress-business.html) template? I played with css quite a bit, but i failed, so I guess it has to do with javascript?
heres the javascript code
(function($) {
var NivoSlider = function(element, options){
// Defaults are below
var settings = $.extend({}, $.fn.nivoSlider.defaults, options);
// Useful variables. Play carefully.
var vars = {
currentSlide: 0,
currentImage: '',
totalSlides: 0,
running: false,
paused: false,
stop: false,
controlNavEl: false
};
// Get this slider
var slider = $(element);
slider.data('nivo:vars', vars).addClass('nivoSlider');
// Find our slider children
var kids = slider.children();
kids.each(function() {
var child = $(this);
var link = '';
if(!child.is('img')){
if(child.is('a')){
child.addClass('nivo-imageLink');
link = child;
}
child = child.find('img:first');
}
// Get img width & height
var childWidth = (childWidth === 0) ? child.attr('width') : child.width(),
childHeight = (childHeight === 0) ? child.attr('height') : child.height();
if(link !== ''){
link.css('display','none');
}
child.css('display','none');
vars.totalSlides++;
});
// If randomStart
if(settings.randomStart){
settings.startSlide = Math.floor(Math.random() * vars.totalSlides);
}
// Set startSlide
if(settings.startSlide > 0){
if(settings.startSlide >= vars.totalSlides) { settings.startSlide = vars.totalSlides - 1; }
vars.currentSlide = settings.startSlide;
}
// Get initial image
if($(kids[vars.currentSlide]).is('img')){
vars.currentImage = $(kids[vars.currentSlide]);
} else {
vars.currentImage = $(kids[vars.currentSlide]).find('img:first');
}
// Show initial link
if($(kids[vars.currentSlide]).is('a')){
$(kids[vars.currentSlide]).css('display','block');
}
// Set first background
var sliderImg = $('<img class="nivo-main-image" src="#" />');
sliderImg.attr('src', vars.currentImage.attr('src')).show();
slider.append(sliderImg);
// Detect Window Resize
$(window).resize(function() {
slider.children('img').width(slider.width());
sliderImg.attr('src', vars.currentImage.attr('src'));
sliderImg.stop().height('auto');
$('.nivo-slice').remove();
$('.nivo-box').remove();
});
//Create caption
slider.append($('<div class="nivo-caption"></div>'));
// Process caption function
var processCaption = function(settings){
var nivoCaption = $('.nivo-caption', slider);
if(vars.currentImage.attr('title') != '' && vars.currentImage.attr('title') != undefined){
var title = vars.currentImage.attr('title');
if(title.substr(0,1) == '#') title = $(title).html();
if(nivoCaption.css('display') == 'block'){
setTimeout(function(){
nivoCaption.html(title);
}, settings.animSpeed);
} else {
nivoCaption.html(title);
nivoCaption.stop().fadeIn(settings.animSpeed);
}
} else {
nivoCaption.stop().fadeOut(settings.animSpeed);
}
}
//Process initial caption
processCaption(settings);
// In the words of Super Mario "let's a go!"
var timer = 0;
if(!settings.manualAdvance && kids.length > 1){
timer = setInterval(function(){ nivoRun(slider, kids, settings, false); }, settings.pauseTime);
}
// Add Direction nav
if(settings.directionNav){
slider.append('<div class="nivo-directionNav"><a class="nivo-prevNav">'+ settings.prevText +'</a><a class="nivo-nextNav">'+ settings.nextText +'</a></div>');
// Hide Direction nav
if(settings.directionNavHide){
$('.nivo-directionNav', slider).hide();
slider.hover(function(){
$('.nivo-directionNav', slider).show();
}, function(){
$('.nivo-directionNav', slider).hide();
});
}
$('a.nivo-prevNav', slider).live('click', function(){
if(vars.running) { return false; }
clearInterval(timer);
timer = '';
vars.currentSlide -= 2;
nivoRun(slider, kids, settings, 'prev');
});
$('a.nivo-nextNav', slider).live('click', function(){
if(vars.running) { return false; }
clearInterval(timer);
timer = '';
nivoRun(slider, kids, settings, 'next');
});
}
// Add Control nav
if(settings.controlNav){
vars.controlNavEl = $('<div class="nivo-controlNav"></div>');
slider.after(vars.controlNavEl);
for(var i = 0; i < kids.length; i++){
if(settings.controlNavThumbs){
vars.controlNavEl.addClass('nivo-thumbs-enabled');
var child = kids.eq(i);
if(!child.is('img')){
child = child.find('img:first');
}
if(child.attr('data-thumb')) vars.controlNavEl.append('<a class="nivo-control" rel="'+ i +'"><img src="'+ child.attr('data-thumb') +'" alt="" /></a>');
} else {
vars.controlNavEl.append('<a class="nivo-control" rel="'+ i +'">'+ (i + 1) +'</a>');
}
}
//Set initial active link
$('a:eq('+ vars.currentSlide +')', vars.controlNavEl).addClass('active');
$('a', vars.controlNavEl).bind('click', function(){
if(vars.running) return false;
if($(this).hasClass('active')) return false;
clearInterval(timer);
timer = '';
sliderImg.attr('src', vars.currentImage.attr('src'));
vars.currentSlide = $(this).attr('rel') - 1;
nivoRun(slider, kids, settings, 'control');
});
}
//For pauseOnHover setting
if(settings.pauseOnHover){
slider.hover(function(){
vars.paused = true;
clearInterval(timer);
timer = '';
}, function(){
vars.paused = false;
// Restart the timer
if(timer === '' && !settings.manualAdvance){
timer = setInterval(function(){ nivoRun(slider, kids, settings, false); }, settings.pauseTime);
}
});
}
// Event when Animation finishes
slider.bind('nivo:animFinished', function(){
sliderImg.attr('src', vars.currentImage.attr('src'));
vars.running = false;
// Hide child links
$(kids).each(function(){
if($(this).is('a')){
$(this).css('display','none');
}
});
// Show current link
if($(kids[vars.currentSlide]).is('a')){
$(kids[vars.currentSlide]).css('display','block');
}
// Restart the timer
if(timer === '' && !vars.paused && !settings.manualAdvance){
timer = setInterval(function(){ nivoRun(slider, kids, settings, false); }, settings.pauseTime);
}
// Trigger the afterChange callback
settings.afterChange.call(this);
});
You are looking in the wrong place. use firebug to inspect and know which css file is being used. the file is default.css. Line 159. Thats what you should be playing with. this is what it looks like
.nivoSlider {
float: left;
position: relative;
width: 100%;
height: 480px;
overflow: hidden;
background: #000
this is the block of code that affects the presentation of the navigation bar. but to eradicate the blackness down there, you can use this close fix
change the property height of the nivoslider class to auto on line 159
change the backgroud property of the navigation class from transparent to black on line 296
change the margin-top property of the id menu class to 316px on line 285
this is not guaranteed to not distort especially the last point. but keep trying.

CKEDITOR add Styling

I'm trying to set some css to the CKEDITOR 4 programmaticly.
This because when a new user comes to the editor i would like to identify him with a different color.
Within the registered style array i do see the added row(CKEDITOR.stylesSet.registered.user0). but the style isn't visible in the editor?
Why is this? and what am i doing wrong?
setStyling: function(editor)
{
var userIds = this.getUserIds(editor);// returns an array with id's
var colors = editor.config.Colors; // Colors are set in the config
for(var i = 0; userIds.length > i; i++)
{
if(CKEDITOR.stylesSet.get('user' + i) === null)
{
CKEDITOR.stylesSet.add('user' + i, [
{ name: 'userColor', element: 'span[data-uid="' + userIds[i] +'"]', styles: { color: colors[i] }}
]);
}
}
}
Another aproach did the job:
var $head = $("iframe").contents().find("head");
var $style = $("iframe").contents().find("#uniqueStyle");
var css = "";
for(var i = 0; userIds.length > i; i++)
{
css += "span[data-uid='" + userIds[i] + "'] { color: " + colors[i] + "; } ";
}
if($style)
{
$style.remove();
}
$('<style id="uniqueStyle" type="text/css"></style>')
.html(css)
.appendTo($head);

Resources