<commit_before>var isMozilla = window.mozRTCPeerConnection && !window.webkitRTCPeerConnection;
if (isMozilla) {
    window.webkitURL = window.URL;
    navigator.webkitGetUserMedia = navigator.mozGetUserMedia;
    window.webkitRTCPeerConnection = window.mozRTCPeerConnection;
    window.RTCSessionDescription = window.mozRTCSessionDescription;
    window.RTCIceCandidate = window.mozRTCIceCandidate;
}

var selfView;
var remoteView;
var callButton;
var audioCheckBox;
var videoCheckBox;
var audioOnlyView;
var signalingChannel;
var pc;
var peer;
var localStream;
var chatDiv;
var chatText;
var chatButton;
var chatCheckBox;
var channel;

if (!window.hasOwnProperty("orientation"))
    window.orientation = -90;

// must use 'url' here since Firefox doesn't understand 'urls'
var configuration = {
  "iceServers": [
  {
    "url": "stun:mmt-stun.verkstad.net"
  },
  {
    "url": "turn:mmt-turn.verkstad.net",
    "username": "webrtc",
    "credential": "secret"
  }
  ]
};
window.onload = function () {
    selfView = document.getElementById("self_view");
    remoteView = document.getElementById("remote_view");
    callButton = document.getElementById("call_but");
    var joinButton = document.getElementById("join_but");
    audioCheckBox = document.getElementById("audio_cb");
    videoCheckBox = document.getElementById("video_cb");
    audioOnlyView = document.getElementById("audio-only-container");
    var shareView = document.getElementById("share-container");
    chatText = document.getElementById("chat_txt");
    chatButton = document.getElementById("chat_but");
    chatDiv = document.getElementById("chat_div");
    chatCheckBox = document.getElementById("chat_cb");

    // if browser doesn't support DataChannels the chat will be disabled.
    if (webkitRTCPeerConnection.prototype.createDataChannel === undefined) {
        chatCheckBox.checked = false;
        chatCheckBox.disabled = true;
    }

    // Store media preferences
    audioCheckBox.onclick = videoCheckBox.onclick = chatCheckBox.onclick = function(evt) {
        localStorage.setItem(this.id, this.checked);
    };

    audioCheckBox.checked = localStorage.getItem("audio_cb") == "true";
    videoCheckBox.checked = localStorage.getItem("video_cb") == "true";

    if (webkitRTCPeerConnection.prototype.createDataChannel !== undefined)
        chatCheckBox.checked = localStorage.getItem("chat_cb") == "true";

    // Check video box if no preferences exist
    if (!localStorage.getItem("video_cb"))
        videoCheckBox.checked = true;

    joinButton.disabled = !navigator.webkitGetUserMedia;
    joinButton.onclick = function (evt) {
        if (!(audioCheckBox.checked || videoCheckBox.checked || chatCheckBox.checked)) {
            alert("Choose at least audio, video or chat.");
            return;
        }

        audioCheckBox.disabled = videoCheckBox.disabled = chatCheckBox.disabled = joinButton.disabled = true;

        // only chat
        if (!(videoCheckBox.checked || audioCheckBox.checked)) peerJoin();

        function peerJoin() {
            var sessionId = document.getElementById("session_txt").value;
            signalingChannel = new SignalingChannel(sessionId);

            // show and update share link
            var link = document.getElementById("share_link");
            var maybeAddHash = window.location.href.indexOf('#') !== -1 ? "" : ("#" + sessionId);
            link.href = link.textContent = window.location.href + maybeAddHash;
            shareView.style.visibility = "visible";

            callButton.onclick = function () {
                start(true);
            };

            // another peer has joined our session
            signalingChannel.onpeer = function (evt) {

                callButton.disabled = false;
                shareView.style.visibility = "hidden";

                peer = evt.peer;
                peer.onmessage = handleMessage;

                peer.ondisconnect = function () {
                    callButton.disabled = true;
                    remoteView.style.visibility = "hidden";
                    if (pc)
                        pc.close();
                    pc = null;
                };
            };
        }

        // video/audio with our without chat
        if (videoCheckBox.checked || audioCheckBox.checked) {
            // get a local stream
            navigator.webkitGetUserMedia({ "audio": audioCheckBox.checked,
                "video": videoCheckBox.checked}, function (stream) {
                // .. show it in a self-view
                selfView.src = URL.createObjectURL(stream);
                // .. and keep it to be sent later
                localStream = stream;

                joinButton.disabled = true;
                chatButton.disabled = true;

                if (videoCheckBox.checked)
                    selfView.style.visibility = "visible";
                else if (audioCheckBox.checked && !(chatCheckBox.checked))
                    audioOnlyView.style.visibility = "visible";

                peerJoin();
            }, logError);
        }
    };

    document.getElementById("owr-logo").onclick = function() {
        window.location.assign("http://www.openwebrtc.io");
    };

    var hash = location.hash.substr(1);
    if (hash) {
        document.getElementById("session_txt").value = hash;
        log("Auto-joining session: " + hash);
        joinButton.click();
    } else {
        // set a random session id
        document.getElementById("session_txt").value = Math.random().toString(16).substr(4);
    }
};

// handle signaling messages received from the other peer
function handleMessage(evt) {
    var message = JSON.parse(evt.data);

    if (!pc && (message.sdp || message.candidate))
        start(false);

    if (message.sdp) {
        var desc = new RTCSessionDescription(message.sdp);
        pc.setRemoteDescription(desc, function () {
            // if we received an offer, we need to create an answer
            if (pc.remoteDescription.type == "offer")
                pc.createAnswer(localDescCreated, logError);
        }, logError);
    } else if (!isNaN(message.orientation) && remoteView) {
        var transform = "rotate(" + message.orientation + "deg)";
        remoteView.style.transform = remoteView.style.webkitTransform = transform;
    } else
        pc.addIceCandidate(new RTCIceCandidate(message.candidate), function () {}, logError);
}

// call start() to initiate
function start(isInitiator) {
    callButton.disabled = true;
    pc = new webkitRTCPeerConnection(configuration);

    // send any ice candidates to the other peer
    pc.onicecandidate = function (evt) {
        if (evt.candidate)
            peer.send(JSON.stringify({ "candidate": evt.candidate }));
    };

    // let the "negotiationneeded" event trigger offer generation
    pc.onnegotiationneeded = function () {
        // check signaling state here because Chrome dispatches negotiationeeded during negotiation
        if (pc.signalingState == "stable")
            pc.createOffer(localDescCreated, logError);
    };

    // start the chat
    if (chatCheckBox.checked) {
        if (isInitiator) {
            channel = pc.createDataChannel("chat");
            setupChat();
        } else {
            pc.ondatachannel = function (evt) {
                channel = evt.channel;
                setupChat();
            };
        }
    }

    // once the remote stream arrives, show it in the remote video element
    pc.onaddstream = function (evt) {
        remoteView.src = URL.createObjectURL(evt.stream);
        if (videoCheckBox.checked)
            remoteView.style.visibility = "visible";
        else if (audioCheckBox.checked && !(chatCheckBox.checked))
            audioOnlyView.style.visibility = "visible";
        sendOrientationUpdate();
    };

    if (audioCheckBox.checked || videoCheckBox.checked) {
        pc.addStream(localStream);
    }

    // the negotiationneeded event is not supported in Firefox
    if (isMozilla && isInitiator)
        pc.onnegotiationneeded();
}

function localDescCreated(desc) {
    pc.setLocalDescription(desc, function () {
        peer.send(JSON.stringify({ "sdp": pc.localDescription }));
    }, logError);
}

function sendOrientationUpdate() {
    peer.send(JSON.stringify({ "orientation": window.orientation + 90 }));
}

window.onorientationchange = function () {
    if (peer)
        sendOrientationUpdate();

    if (selfView) {
        var transform = "rotate(" + (window.orientation + 90) + "deg)";
        selfView.style.transform = selfView.style.webkitTransform = transform;
    }
};

function logError(error) {
    if (error) {
        if (error.name && error.message)
            log(error.name + ": " + error.message);
        else
            log(error);
    } else
        log("Error (no error message)");
}

function log(msg) {
    log.div = log.div || document.getElementById("log_div");
    log.div.appendChild(document.createTextNode(msg));
    log.div.appendChild(document.createElement("br"));
}

// setup chat
function setupChat() {
    channel.onopen = function () {
        chatDiv.style.visibility = "visible";
        chatText.style.visibility = "visible";
        chatButton.style.visibility = "visible";
        chatButton.disabled = false;

        //On enter press - send text message.
        chatText.onkeyup = function(event) {
            if (event.keyCode == 13) {
                chatButton.click();
            }
        };

        chatButton.onclick = function () {
            if(chatText.value) {
                postChatMessage(chatText.value, true);
                channel.send(chatText.value);
                chatText.value = "";
                chatText.placeholder = "";
            }
        };
    };

    // recieve data from remote user
    channel.onmessage = function (evt) {
        postChatMessage(evt.data);
    };

    function postChatMessage(msg, author) {
        var messageNode = document.createElement('div');
        var messageContent = document.createElement('div');
        messageNode.classList.add('chatMessage');
        messageContent.textContent = msg;
        messageNode.appendChild(messageContent);

        if (author) {
            messageNode.classList.add('selfMessage');
        } else {
            messageNode.classList.add('remoteMessage');
        }

        chatDiv.appendChild(messageNode);
        chatDiv.scrollTop = chatDiv.scrollHeight;
    }
}
<commit_msg>Added console logs for session descriptions and ICE candidates. Apprtc does this, and it helps a lot when working with webrtc.<commit_after>var isMozilla = window.mozRTCPeerConnection && !window.webkitRTCPeerConnection;
if (isMozilla) {
    window.webkitURL = window.URL;
    navigator.webkitGetUserMedia = navigator.mozGetUserMedia;
    window.webkitRTCPeerConnection = window.mozRTCPeerConnection;
    window.RTCSessionDescription = window.mozRTCSessionDescription;
    window.RTCIceCandidate = window.mozRTCIceCandidate;
}

var selfView;
var remoteView;
var callButton;
var audioCheckBox;
var videoCheckBox;
var audioOnlyView;
var signalingChannel;
var pc;
var peer;
var localStream;
var chatDiv;
var chatText;
var chatButton;
var chatCheckBox;
var channel;

if (!window.hasOwnProperty("orientation"))
    window.orientation = -90;

// must use 'url' here since Firefox doesn't understand 'urls'
var configuration = {
  "iceServers": [
  {
    "url": "stun:mmt-stun.verkstad.net"
  },
  {
    "url": "turn:mmt-turn.verkstad.net",
    "username": "webrtc",
    "credential": "secret"
  }
  ]
};
window.onload = function () {
    selfView = document.getElementById("self_view");
    remoteView = document.getElementById("remote_view");
    callButton = document.getElementById("call_but");
    var joinButton = document.getElementById("join_but");
    audioCheckBox = document.getElementById("audio_cb");
    videoCheckBox = document.getElementById("video_cb");
    audioOnlyView = document.getElementById("audio-only-container");
    var shareView = document.getElementById("share-container");
    chatText = document.getElementById("chat_txt");
    chatButton = document.getElementById("chat_but");
    chatDiv = document.getElementById("chat_div");
    chatCheckBox = document.getElementById("chat_cb");

    // if browser doesn't support DataChannels the chat will be disabled.
    if (webkitRTCPeerConnection.prototype.createDataChannel === undefined) {
        chatCheckBox.checked = false;
        chatCheckBox.disabled = true;
    }

    // Store media preferences
    audioCheckBox.onclick = videoCheckBox.onclick = chatCheckBox.onclick = function(evt) {
        localStorage.setItem(this.id, this.checked);
    };

    audioCheckBox.checked = localStorage.getItem("audio_cb") == "true";
    videoCheckBox.checked = localStorage.getItem("video_cb") == "true";

    if (webkitRTCPeerConnection.prototype.createDataChannel !== undefined)
        chatCheckBox.checked = localStorage.getItem("chat_cb") == "true";

    // Check video box if no preferences exist
    if (!localStorage.getItem("video_cb"))
        videoCheckBox.checked = true;

    joinButton.disabled = !navigator.webkitGetUserMedia;
    joinButton.onclick = function (evt) {
        if (!(audioCheckBox.checked || videoCheckBox.checked || chatCheckBox.checked)) {
            alert("Choose at least audio, video or chat.");
            return;
        }

        audioCheckBox.disabled = videoCheckBox.disabled = chatCheckBox.disabled = joinButton.disabled = true;

        // only chat
        if (!(videoCheckBox.checked || audioCheckBox.checked)) peerJoin();

        function peerJoin() {
            var sessionId = document.getElementById("session_txt").value;
            signalingChannel = new SignalingChannel(sessionId);

            // show and update share link
            var link = document.getElementById("share_link");
            var maybeAddHash = window.location.href.indexOf('#') !== -1 ? "" : ("#" + sessionId);
            link.href = link.textContent = window.location.href + maybeAddHash;
            shareView.style.visibility = "visible";

            callButton.onclick = function () {
                start(true);
            };

            // another peer has joined our session
            signalingChannel.onpeer = function (evt) {

                callButton.disabled = false;
                shareView.style.visibility = "hidden";

                peer = evt.peer;
                peer.onmessage = handleMessage;

                peer.ondisconnect = function () {
                    callButton.disabled = true;
                    remoteView.style.visibility = "hidden";
                    if (pc)
                        pc.close();
                    pc = null;
                };
            };
        }

        // video/audio with our without chat
        if (videoCheckBox.checked || audioCheckBox.checked) {
            // get a local stream
            navigator.webkitGetUserMedia({ "audio": audioCheckBox.checked,
                "video": videoCheckBox.checked}, function (stream) {
                // .. show it in a self-view
                selfView.src = URL.createObjectURL(stream);
                // .. and keep it to be sent later
                localStream = stream;

                joinButton.disabled = true;
                chatButton.disabled = true;

                if (videoCheckBox.checked)
                    selfView.style.visibility = "visible";
                else if (audioCheckBox.checked && !(chatCheckBox.checked))
                    audioOnlyView.style.visibility = "visible";

                peerJoin();
            }, logError);
        }
    };

    document.getElementById("owr-logo").onclick = function() {
        window.location.assign("http://www.openwebrtc.io");
    };

    var hash = location.hash.substr(1);
    if (hash) {
        document.getElementById("session_txt").value = hash;
        log("Auto-joining session: " + hash);
        joinButton.click();
    } else {
        // set a random session id
        document.getElementById("session_txt").value = Math.random().toString(16).substr(4);
    }
};

// handle signaling messages received from the other peer
function handleMessage(evt) {
    var message = JSON.parse(evt.data);

    if (!pc && (message.sdp || message.candidate))
        start(false);

    if (message.sdp) {
        var desc = new RTCSessionDescription(message.sdp);
        pc.setRemoteDescription(desc, function () {
            // if we received an offer, we need to create an answer
            if (pc.remoteDescription.type == "offer")
                pc.createAnswer(localDescCreated, logError);
        }, logError);
    } else if (!isNaN(message.orientation) && remoteView) {
        var transform = "rotate(" + message.orientation + "deg)";
        remoteView.style.transform = remoteView.style.webkitTransform = transform;
    } else
        pc.addIceCandidate(new RTCIceCandidate(message.candidate), function () {}, logError);
}

// call start() to initiate
function start(isInitiator) {
    callButton.disabled = true;
    pc = new webkitRTCPeerConnection(configuration);

    // send any ice candidates to the other peer
    pc.onicecandidate = function (evt) {
        if (evt.candidate) {
            peer.send(JSON.stringify({ "candidate": evt.candidate }));
            console.log("candidate emitted: " + evt.candidate.candidate);
        }
    };

    // let the "negotiationneeded" event trigger offer generation
    pc.onnegotiationneeded = function () {
        // check signaling state here because Chrome dispatches negotiationeeded during negotiation
        if (pc.signalingState == "stable")
            pc.createOffer(localDescCreated, logError);
    };

    // start the chat
    if (chatCheckBox.checked) {
        if (isInitiator) {
            channel = pc.createDataChannel("chat");
            setupChat();
        } else {
            pc.ondatachannel = function (evt) {
                channel = evt.channel;
                setupChat();
            };
        }
    }

    // once the remote stream arrives, show it in the remote video element
    pc.onaddstream = function (evt) {
        remoteView.src = URL.createObjectURL(evt.stream);
        if (videoCheckBox.checked)
            remoteView.style.visibility = "visible";
        else if (audioCheckBox.checked && !(chatCheckBox.checked))
            audioOnlyView.style.visibility = "visible";
        sendOrientationUpdate();
    };

    if (audioCheckBox.checked || videoCheckBox.checked) {
        pc.addStream(localStream);
    }

    // the negotiationneeded event is not supported in Firefox
    if (isMozilla && isInitiator)
        pc.onnegotiationneeded();
}

function localDescCreated(desc) {
    pc.setLocalDescription(desc, function () {
        peer.send(JSON.stringify({ "sdp": pc.localDescription }));
        console.log("localDescription set and sent to peer, type: " + pc.localDescription.type + ", sdp: " + pc.localDescription.sdp);
    }, logError);
}

function sendOrientationUpdate() {
    peer.send(JSON.stringify({ "orientation": window.orientation + 90 }));
}

window.onorientationchange = function () {
    if (peer)
        sendOrientationUpdate();

    if (selfView) {
        var transform = "rotate(" + (window.orientation + 90) + "deg)";
        selfView.style.transform = selfView.style.webkitTransform = transform;
    }
};

function logError(error) {
    if (error) {
        if (error.name && error.message)
            log(error.name + ": " + error.message);
        else
            log(error);
    } else
        log("Error (no error message)");
}

function log(msg) {
    log.div = log.div || document.getElementById("log_div");
    log.div.appendChild(document.createTextNode(msg));
    log.div.appendChild(document.createElement("br"));
}

// setup chat
function setupChat() {
    channel.onopen = function () {
        chatDiv.style.visibility = "visible";
        chatText.style.visibility = "visible";
        chatButton.style.visibility = "visible";
        chatButton.disabled = false;

        //On enter press - send text message.
        chatText.onkeyup = function(event) {
            if (event.keyCode == 13) {
                chatButton.click();
            }
        };

        chatButton.onclick = function () {
            if(chatText.value) {
                postChatMessage(chatText.value, true);
                channel.send(chatText.value);
                chatText.value = "";
                chatText.placeholder = "";
            }
        };
    };

    // recieve data from remote user
    channel.onmessage = function (evt) {
        postChatMessage(evt.data);
    };

    function postChatMessage(msg, author) {
        var messageNode = document.createElement('div');
        var messageContent = document.createElement('div');
        messageNode.classList.add('chatMessage');
        messageContent.textContent = msg;
        messageNode.appendChild(messageContent);

        if (author) {
            messageNode.classList.add('selfMessage');
        } else {
            messageNode.classList.add('remoteMessage');
        }

        chatDiv.appendChild(messageNode);
        chatDiv.scrollTop = chatDiv.scrollHeight;
    }
}
<|endoftext|>


<commit_before>'use strict'

const fs = require('fs')
const gm = require('gm').subClass({imageMagick: true})
const aws = require('aws-sdk')
const mime = require('mime')
const BUCKET = process.env.BUCKET
const s3 = new aws.S3({apiVersion: '2006-03-01'})

exports.hasImage = function (Model, options) {
  const name = options.name
  const Name = name[0].toUpperCase() + name.slice(1)

  Model.prototype[`upload${Name}`] = function (file) {
    return new Upload(file, this, options).send()
  }

  Model.prototype[`${name}Key`] = function (size) {
    const ext = this[`${name}_ext`]
    return `${this.tableName}/${this.id}/${name}/${size}.${ext}`
  }

  Model.prototype[`${name}Path`] = function (size) {
    const key = this[`${name}Key`](size)
    const updated_at = this[`${name}_updated_at`]
    if (!updated_at) return null
    return `/assets/${key}?${+updated_at}`
  }
}

class Upload {

  constructor (file, model, options) {
    this.file = file
    this.model = model
    this.name = options.name
    this.sizes = Object.assign(options.sizes, {original: null})
  }

  get ext () {
    return mime.extension(this.mimetype)
  }

  get path () {
    return this.file.path
  }

  get mimetype () {
    return this.file.mimetype
  }

  s3Key (size) {
    return `${this.model.tableName}/${this.model.id}/${this.name}/${size}.${this.ext}`
  }

  cleanup () {
    fs.unlink(this.path)
  }

  send () {
    return Promise.all(
      Object.keys(this.sizes).map(this.put.bind(this))
    ).then(() => {
      this.cleanup()
      return this.model.update({
        [`${this.name}_updated_at`]: new Date(),
        [`${this.name}_ext`]: this.ext
      })
    }).catch((e) => {
      this.cleanup()
      throw e
    })
  }

  stream (size) {
    if (size === 'original') return fs.createReadStream(this.path)
    let width = this.sizes[size]
    return gm(this.path).resize(width, width, '>').noProfile().stream(this.ext)
  }

  put (size) {
    return new Promise((resolve, reject) => {
      s3.upload({
        ACL: 'public-read',
        Body: this.stream(size),
        Bucket: BUCKET,
        CacheControl: `max-age=${60 * 60 * 24 * 7}, public`,
        ContentType: this.mimetype,
        Key: this.s3Key(size)
      }, e => e ? reject(e) : resolve())
    })
  }

}
<commit_msg>Default images.<commit_after>'use strict'

const fs = require('fs')
const gm = require('gm').subClass({imageMagick: true})
const aws = require('aws-sdk')
const mime = require('mime')
const BUCKET = process.env.BUCKET
const s3 = new aws.S3({apiVersion: '2006-03-01'})
const assets = require('./assets')

exports.hasImage = function (Model, options) {
  const defaults = options.defaults
  const name = options.name
  const Name = name[0].toUpperCase() + name.slice(1)

  Model.prototype[`upload${Name}`] = function (file) {
    return new Upload(file, this, options).send()
  }

  Model.prototype[`${name}Key`] = function (size) {
    const ext = this[`${name}_ext`]
    return `${this.tableName}/${this.id}/${name}/${size}.${ext}`
  }

  Model.prototype[`${name}Path`] = function (size) {
    const key = this[`${name}Key`](size)
    const updated_at = this[`${name}_updated_at`]
    if (!updated_at) {
      return defaults ? assets.path(defaults[this.id % defaults.length]) : null
    }
    return `/assets/${key}?${+updated_at}`
  }
}

class Upload {

  constructor (file, model, options) {
    this.file = file
    this.model = model
    this.name = options.name
    this.sizes = Object.assign(options.sizes, {original: null})
  }

  get ext () {
    return mime.extension(this.mimetype)
  }

  get path () {
    return this.file.path
  }

  get mimetype () {
    return this.file.mimetype
  }

  s3Key (size) {
    return `${this.model.tableName}/${this.model.id}/${this.name}/${size}.${this.ext}`
  }

  cleanup () {
    fs.unlink(this.path)
  }

  send () {
    return Promise.all(
      Object.keys(this.sizes).map(this.put.bind(this))
    ).then(() => {
      this.cleanup()
      return this.model.update({
        [`${this.name}_updated_at`]: new Date(),
        [`${this.name}_ext`]: this.ext
      })
    }).catch((e) => {
      this.cleanup()
      throw e
    })
  }

  stream (size) {
    if (size === 'original') return fs.createReadStream(this.path)
    let width = this.sizes[size]
    return gm(this.path).resize(width, width, '>').noProfile().stream(this.ext)
  }

  put (size) {
    return new Promise((resolve, reject) => {
      s3.upload({
        ACL: 'public-read',
        Body: this.stream(size),
        Bucket: BUCKET,
        CacheControl: `max-age=${60 * 60 * 24 * 7}, public`,
        ContentType: this.mimetype,
        Key: this.s3Key(size)
      }, e => e ? reject(e) : resolve())
    })
  }

}
<|endoftext|>


<commit_before>if (window.midgardCreate === undefined) {
  window.midgardCreate = {};
}
if (window.midgardCreate.locale === undefined) {
  window.midgardCreate.locale = {};
}

window.midgardCreate.locale.it = {
  // Session-state buttons for the main toolbar
  'Save': 'Salva',
  'Saving': 'Salvataggio',
  'Cancel': 'Cancella',
  'Edit': 'Modifica',
  // Storage status messages
  'localModification': 'Articolo "<%= label %>" in questa pagina hanno modifiche locali',
  'localModifications': '<%= number %> articoli in questa pagina hanno modifiche locali',
  'Restore': 'Ripristina',
  'Ignore': 'Ignora',
  'saveSuccess': 'Articolo "<%= label %>" salvato con successo',
  'saveSuccessMultiple': '<%= number %> articoli salvati con successo',
  'saveError': 'Errore durante il salvataggio
<%= error %>',
  // Tagging
  'Item tags': 'Tags articolo',
  'Suggested tags': 'Tags suggerite',
  'Tags': 'Tags',
  'add a tag': 'Aggiungi una parola chiave',
  // Collection widgets
  'Add': 'Aggiungi',
  'Choose type to add': 'Scegli il tipo da aggiungere'
};
<commit_msg>Update locale_it.js<commit_after>if (window.midgardCreate === undefined) {
  window.midgardCreate = {};
}
if (window.midgardCreate.locale === undefined) {
  window.midgardCreate.locale = {};
}

window.midgardCreate.locale.it = {
  // Session-state buttons for the main toolbar
  'Save': 'Salva',
  'Saving': 'Salvataggio',
  'Cancel': 'Esci',
  'Edit': 'Modifica',
  // Storage status messages
  'localModification': 'Articolo "<%= label %>" in questa pagina hanno modifiche locali',
  'localModifications': '<%= number %> articoli in questa pagina hanno modifiche locali',
  'Restore': 'Ripristina',
  'Ignore': 'Ignora',
  'saveSuccess': 'Articolo "<%= label %>" salvato con successo',
  'saveSuccessMultiple': '<%= number %> articoli salvati con successo',
  'saveError': 'Errore durante il salvataggio
<%= error %>',
  // Tagging
  'Item tags': 'Tags articolo',
  'Suggested tags': 'Tags suggerite',
  'Tags': 'Tags',
  'add a tag': 'Aggiungi una parola chiave',
  // Collection widgets
  'Add': 'Aggiungi',
  'Choose type to add': 'Scegli il tipo da aggiungere'
};
<|endoftext|>


<commit_before>'use strict';

class Markov {

  constructor(text) {
    this.dict = this._parseText(text);
    this.keys = Object.keys(this.dict);

    this.keys.length < 30
      ? this.maxLength = this.keys.length + 10
      : this.maxLength = 30;
  }

  getRandomKey() {
    return this.keys[Math.floor(Math.random() * this.keys.length)];
  }

  getRandomValue(key) {
    return this.dict[key][Math.floor(Math.random() * this.dict[key].length)];
  }

  getCapitalizedKey() {
    let tries = this.maxLength;
    let key;

    while (tries--) {
      key = this.getRandomKey();

      if (/[A-Z]/.test(key.charAt(0)))
        break;
    }

    return key;
  }

  generate(sentenceCount) {
    let sentences = [];

    while (sentenceCount--) {
      this.maxLength = 30;

      let sentence = [];
      let initKey = this.getCapitalizedKey();
      sentence = sentence.concat(initKey.split(' '));

      while (this.maxLength) {
        let search = sentence.slice(-2).join(' ');
        let found = this.getRandomValue(search);
        sentence.push(found);

        if (/\.|\?|\!/.test(sentence.slice(-1))) break;
        this.maxLength = this.maxLength - 1;
      }
      sentences.push(sentence.join(' '));
    }

    return sentences.join(' ')
  }

// private

  _parseText(text) {
    let dict = {};
    text
      .match(/\S+\s*/g)
      .map(function(item) {
        return item.trim();
      })
      .forEach(function(item, index, arr) {
        if (index < arr.length - 2) {
          let key = [item, arr[index + 1]].join(' ');
          dict[key] = dict[key] || [];
          dict[key].push(arr[index + 2]);
        }
      });

    return dict;
  }

  _random() {
    return this.words[key]
      ? this._getRandomElement(this.words[key])
      : this._getRandomElement(this.words[this._getRandomKey()]);
  }

  _last(arr) {
    return arr[arr.length - 1];
  }
} // end class

module.exports = Markov;
<commit_msg>comments cleanup<commit_after>'use strict';

class Markov {
  constructor(text) {
    this.dict = this._parseText(text);
    this.keys = Object.keys(this.dict);

    this.keys.length < 30
      ? this.maxLength = this.keys.length + 10
      : this.maxLength = 30;
  }

  getRandomKey() {
    return this.keys[Math.floor(Math.random() * this.keys.length)];
  }

  getRandomValue(key) {
    return this.dict[key][Math.floor(Math.random() * this.dict[key].length)];
  }

  getCapitalizedKey() {
    let tries = this.maxLength;
    let key;

    while (tries--) {
      key = this.getRandomKey();

      if (/[A-Z]/.test(key.charAt(0)))
        break;
    }

    return key;
  }

  generate(sentenceCount) {
    let sentences = [];

    while (sentenceCount--) {
      this.maxLength = 30;

      let sentence = [];
      let initKey = this.getCapitalizedKey();
      sentence = sentence.concat(initKey.split(' '));

      while (this.maxLength) {
        let search = sentence.slice(-2).join(' ');
        let found = this.getRandomValue(search);
        sentence.push(found);

        if (/\.|\?|\!/.test(sentence.slice(-1))) break;
        this.maxLength = this.maxLength - 1;
      }
      sentences.push(sentence.join(' '));
    }

    return sentences.join(' ')
  }

  // PRIVATE

  _parseText(text) {
    let dict = {};
    text
      .match(/\S+\s*/g)
      .map(function(item) {
        return item.trim();
      })
      .forEach(function(item, index, arr) {
        if (index < arr.length - 2) {
          let key = [item, arr[index + 1]].join(' ');
          dict[key] = dict[key] || [];
          dict[key].push(arr[index + 2]);
        }
      });

    return dict;
  }

  _random() {
    return this.words[key]
      ? this._getRandomElement(this.words[key])
      : this._getRandomElement(this.words[this._getRandomKey()]);
  }

  _last(arr) {
    return arr[arr.length - 1];
  }
}

module.exports = Markov;
<|endoftext|>


<commit_before>describe('dialogFieldRefresh', function() {
  describe('#addOptionsToDropDownList', function() {
    var data = {};

    beforeEach(function() {
      var html = "";
      html += '<select class="dynamic-drop-down-345 selectpicker">';
      html += '</select>';
      setFixtures(html);
    });

    context('when the refreshed values contain a checked value', function() {
      context('when the refreshed values contain a null key', function() {
        beforeEach(function() {
          data = {values: {refreshed_values: [[null, 'not test'], ['123', 'is test']], checked_value: 123}};
        });

        it('it does not blow up', function() {
          var test = function() {
            dialogFieldRefresh.addOptionsToDropDownList(data, 345);
          };
          expect(test).not.toThrow();
        });

        it('selects the option that corresponds to the checked value', function() {
          dialogFieldRefresh.addOptionsToDropDownList(data, 345);
          expect($('.dynamic-drop-down-345.selectpicker').val()).toBe('123');
        });
      });
    });

    context('when the refreshed values do not contain a checked value', function() {
      beforeEach(function() {
        data = {values: {refreshed_values: [["test", "test"], ["not test", "not test"]], checked_value: null}};
      });

      it('selects the first option', function() {
        dialogFieldRefresh.addOptionsToDropDownList(data, 345);
        expect($('.dynamic-drop-down-345.selectpicker').val()).toBe('test');
      });
    });
  });

  describe('#refreshDropDownList', function() {
    beforeEach(function() {
      spyOn(dialogFieldRefresh, 'addOptionsToDropDownList');

      spyOn($.fn, 'selectpicker');
      spyOn($, 'post').and.callFake(function() {
        var d = $.Deferred();
        d.resolve("the data");
        return d.promise();
      });
    });

    it('calls addOptionsToDropDownList', function() {
      dialogFieldRefresh.refreshDropDownList('abc', 123, 'test');
      expect(dialogFieldRefresh.addOptionsToDropDownList).toHaveBeenCalledWith("the data", 123);
    });

    it('ensures the select picker is refreshed', function() {
      dialogFieldRefresh.refreshDropDownList('abc', 123, 'test');
      expect($.fn.selectpicker).toHaveBeenCalledWith('refresh');
    });

    it('sets the value in the select picker', function() {
      dialogFieldRefresh.refreshDropDownList('abc', 123, 'test');
      expect($.fn.selectpicker).toHaveBeenCalledWith('val', 'test');
    });

    it('uses the correct selector', function() {
      dialogFieldRefresh.refreshDropDownList('abc', 123, 'test');
      expect($.fn.selectpicker.calls.mostRecent().object.selector).toEqual('#abc');
    });
  });

  describe('#initializeDialogSelectPicker', function() {
    var fieldName, selectedValue, url;

    beforeEach(function() {
      spyOn(dialogFieldRefresh, 'triggerAutoRefresh');
      spyOn(window, 'miqInitSelectPicker');
      spyOn(window, 'miqSelectPickerEvent');
      spyOn($.fn, 'selectpicker');
      fieldName = 'fieldName';
      fieldId = 'fieldId';
      selectedValue = 'selectedValue';
      url = 'url';

      var html = "";
      html += '<select id=fieldName class="dynamic-drop-down-193 selectpicker">';
      html += '<option value="1">1</option>';
      html += '<option value="2" selected="selected">2</option>';
      html += '</select>';

      setFixtures(html);
    });

    it('initializes the select picker', function() {
      dialogFieldRefresh.initializeDialogSelectPicker(fieldName, fieldId, selectedValue, url);
      expect(window.miqInitSelectPicker).toHaveBeenCalled();
    });

    it('sets the value of the select picker', function() {
      dialogFieldRefresh.initializeDialogSelectPicker(fieldName, fieldId, selectedValue, url);
      expect($.fn.selectpicker).toHaveBeenCalledWith('val', 'selectedValue');
    });

    it('uses the correct selector', function() {
      dialogFieldRefresh.initializeDialogSelectPicker(fieldName, fieldId, selectedValue, url);
      expect($.fn.selectpicker.calls.mostRecent().object.selector).toEqual('#fieldName');
    });

    it('sets up the select picker event', function() {
      dialogFieldRefresh.initializeDialogSelectPicker(fieldName, fieldId, selectedValue, url);
      expect(window.miqSelectPickerEvent).toHaveBeenCalledWith('fieldName', 'url');
    });

    it('triggers the auto refresh when the drop down changes', function() {
      dialogFieldRefresh.initializeDialogSelectPicker(fieldName, fieldId, selectedValue, url);
      $("#"+fieldName).trigger('change');
      expect(dialogFieldRefresh.triggerAutoRefresh).toHaveBeenCalledWith(fieldId, 'true');
    });
  });
});
<commit_msg>js test - dialogFieldRefresh.initializeDialogSelectPicker when triggerAutoRefresh is false (transferred from ManageIQ/manageiq@bd428c0c6a36b578326d36fd2b70a9bdf7c618ad)<commit_after>describe('dialogFieldRefresh', function() {
  describe('#addOptionsToDropDownList', function() {
    var data = {};

    beforeEach(function() {
      var html = "";
      html += '<select class="dynamic-drop-down-345 selectpicker">';
      html += '</select>';
      setFixtures(html);
    });

    context('when the refreshed values contain a checked value', function() {
      context('when the refreshed values contain a null key', function() {
        beforeEach(function() {
          data = {values: {refreshed_values: [[null, 'not test'], ['123', 'is test']], checked_value: 123}};
        });

        it('it does not blow up', function() {
          var test = function() {
            dialogFieldRefresh.addOptionsToDropDownList(data, 345);
          };
          expect(test).not.toThrow();
        });

        it('selects the option that corresponds to the checked value', function() {
          dialogFieldRefresh.addOptionsToDropDownList(data, 345);
          expect($('.dynamic-drop-down-345.selectpicker').val()).toBe('123');
        });
      });
    });

    context('when the refreshed values do not contain a checked value', function() {
      beforeEach(function() {
        data = {values: {refreshed_values: [["test", "test"], ["not test", "not test"]], checked_value: null}};
      });

      it('selects the first option', function() {
        dialogFieldRefresh.addOptionsToDropDownList(data, 345);
        expect($('.dynamic-drop-down-345.selectpicker').val()).toBe('test');
      });
    });
  });

  describe('#refreshDropDownList', function() {
    beforeEach(function() {
      spyOn(dialogFieldRefresh, 'addOptionsToDropDownList');

      spyOn($.fn, 'selectpicker');
      spyOn($, 'post').and.callFake(function() {
        var d = $.Deferred();
        d.resolve("the data");
        return d.promise();
      });
    });

    it('calls addOptionsToDropDownList', function() {
      dialogFieldRefresh.refreshDropDownList('abc', 123, 'test');
      expect(dialogFieldRefresh.addOptionsToDropDownList).toHaveBeenCalledWith("the data", 123);
    });

    it('ensures the select picker is refreshed', function() {
      dialogFieldRefresh.refreshDropDownList('abc', 123, 'test');
      expect($.fn.selectpicker).toHaveBeenCalledWith('refresh');
    });

    it('sets the value in the select picker', function() {
      dialogFieldRefresh.refreshDropDownList('abc', 123, 'test');
      expect($.fn.selectpicker).toHaveBeenCalledWith('val', 'test');
    });

    it('uses the correct selector', function() {
      dialogFieldRefresh.refreshDropDownList('abc', 123, 'test');
      expect($.fn.selectpicker.calls.mostRecent().object.selector).toEqual('#abc');
    });
  });

  describe('#initializeDialogSelectPicker', function() {
    var fieldName, selectedValue, url;

    beforeEach(function() {
      spyOn(dialogFieldRefresh, 'triggerAutoRefresh');
      spyOn(window, 'miqInitSelectPicker');
      spyOn(window, 'miqSelectPickerEvent');
      spyOn($.fn, 'selectpicker');
      fieldName = 'fieldName';
      fieldId = 'fieldId';
      selectedValue = 'selectedValue';
      url = 'url';

      var html = "";
      html += '<select id=fieldName class="dynamic-drop-down-193 selectpicker">';
      html += '<option value="1">1</option>';
      html += '<option value="2" selected="selected">2</option>';
      html += '</select>';

      setFixtures(html);
    });

    it('initializes the select picker', function() {
      dialogFieldRefresh.initializeDialogSelectPicker(fieldName, fieldId, selectedValue, url);
      expect(window.miqInitSelectPicker).toHaveBeenCalled();
    });

    it('sets the value of the select picker', function() {
      dialogFieldRefresh.initializeDialogSelectPicker(fieldName, fieldId, selectedValue, url);
      expect($.fn.selectpicker).toHaveBeenCalledWith('val', 'selectedValue');
    });

    it('uses the correct selector', function() {
      dialogFieldRefresh.initializeDialogSelectPicker(fieldName, fieldId, selectedValue, url);
      expect($.fn.selectpicker.calls.mostRecent().object.selector).toEqual('#fieldName');
    });

    it('sets up the select picker event', function() {
      dialogFieldRefresh.initializeDialogSelectPicker(fieldName, fieldId, selectedValue, url);
      expect(window.miqSelectPickerEvent).toHaveBeenCalledWith('fieldName', 'url');
    });

    it('triggers the auto refresh when the drop down changes', function() {
      dialogFieldRefresh.initializeDialogSelectPicker(fieldName, fieldId, selectedValue, url);
      $("#" + fieldName).trigger('change');
      expect(dialogFieldRefresh.triggerAutoRefresh).toHaveBeenCalledWith(fieldId, 'true');
    });

    it('triggers autorefresh with "false" when triggerAutoRefresh arg is false', function() {
      dialogFieldRefresh.initializeDialogSelectPicker(fieldName, fieldId, selectedValue, url, 'false');
      $("#" + fieldName).trigger('change');
      expect(dialogFieldRefresh.triggerAutoRefresh).toHaveBeenCalledWith(fieldId, 'false');
    });
  });
});
<|endoftext|>


<commit_before>import { ClientFunction, Selector } from 'testcafe';

const URL = process.env.NODE_ENV === 'ci' ?
	'http://sg.vinylwhere.xyz' :
	'http://localhost:8080'

const getWindowLocation = ClientFunction(() => window.location)

fixture `VinylWhere Functional Tests`
    .page `${URL}`;

test('Loading the app shows results', async t => {
	await t.expect(Selector("#results").innerText).contains('2046 OST Vinyl Record')
})

test('Search refines the results', async t => {
	await t
		.typeText('#search', 'U2')
		.expect(Selector('#results').innerText).contains('The Joshua Tree')
})

test('Search updates the URL', async t => {
	const searchTerm = 'CoolArtist'

	await t.typeText('#search', searchTerm)
	await t.wait(500) // search is throttled

	const location = await getWindowLocation()
	await t.expect(location.hash).eql(`#${searchTerm}`)
})

test('Pressing / focuses the search bar', async t => {
	await t
		.click('h1')
		.expect(Selector('#search').focused).notOk()

	await t
		.pressKey('/')
		.expect(Selector('#search').focused).ok()
})

test('Clicking the logo removes the search', async t => {
	await t
		.typeText('#search', 'some search term')
		.wait(500) // search is throttled
		.click('h1')

	const location = await getWindowLocation()
	await t
		.expect(location.hash).eql('')
})

test('Visiting a URL with a search term shows correct results', async t => {
	await t
		.navigateTo('#U2')
		.expect(Selector('#results').innerText).contains('The Joshua Tree')
		.expect(Selector('#search').value).eql('U2')
})
<commit_msg>Fix CI test URL<commit_after>import { ClientFunction, Selector } from 'testcafe';

const URL = process.env.NODE_ENV === 'ci' ?
	'https://vinylwhere.netlify.com' :
	'http://localhost:8080'

const getWindowLocation = ClientFunction(() => window.location)

fixture `VinylWhere Functional Tests`
    .page `${URL}`;

test('Loading the app shows results', async t => {
	await t.expect(Selector("#results").innerText).contains('2046 OST Vinyl Record')
})

test('Search refines the results', async t => {
	await t
		.typeText('#search', 'U2')
		.expect(Selector('#results').innerText).contains('The Joshua Tree')
})

test('Search updates the URL', async t => {
	const searchTerm = 'CoolArtist'

	await t.typeText('#search', searchTerm)
	await t.wait(500) // search is throttled

	const location = await getWindowLocation()
	await t.expect(location.hash).eql(`#${searchTerm}`)
})

test('Pressing / focuses the search bar', async t => {
	await t
		.click('h1')
		.expect(Selector('#search').focused).notOk()

	await t
		.pressKey('/')
		.expect(Selector('#search').focused).ok()
})

test('Clicking the logo removes the search', async t => {
	await t
		.typeText('#search', 'some search term')
		.wait(500) // search is throttled
		.click('h1')

	const location = await getWindowLocation()
	await t
		.expect(location.hash).eql('')
})

test('Visiting a URL with a search term shows correct results', async t => {
	await t
		.navigateTo('#U2')
		.expect(Selector('#results').innerText).contains('The Joshua Tree')
		.expect(Selector('#search').value).eql('U2')
})
<|endoftext|>


<commit_before>import request from 'axios'
import { auth, handleError } from '../constants'
import { URL } from 'constants/URL'
import NOTI from '../constants/Noti'

const API_URL = `${URL}/notification`
const appVersion = '0.1.15'

export const checkVersion = () => async dispatch => {
  try {
    const { data } = await request.get(
      `${API_URL}/version?version=${appVersion}`
    )
    dispatch({
      type: NOTI.CHECK_VERSION,
      data
    })
  } catch (error) {
    console.error(error.response || error)
    handleError(error, dispatch)
  }
}

export const clearRewards = () => ({
  type: NOTI.CLEAR_REWARDS
})

export const clearNotifications = () => ({
  type: NOTI.CLEAR
})

export const fetchNotifications = () => async dispatch => {
  try {
    if (auth().headers.authorization === null) {
      const { data } = await request.get(`${API_URL}/chatSubject`)
      dispatch({
        type: NOTI.LOAD,
        data: {
          notifications: [],
          rewards: [],
          totalRewardAmount: 0,
          currentChatSubject: data
        }
      })
    } else {
      const { data } = await request.get(API_URL, auth())
      dispatch({
        type: NOTI.LOAD,
        data
      })
    }
    return Promise.resolve()
  } catch (error) {
    console.error(error.response || error)
    handleError(error, dispatch)
  }
}

export const loadMoreNotifications = lastId => async dispatch => {
  try {
    const { data } = await request.get(
      `${API_URL}/more?lastId=${lastId}`,
      auth()
    )
    dispatch({
      type: NOTI.LOAD_MORE,
      data
    })
    return Promise.resolve()
  } catch (error) {
    console.error(error.response || error)
    handleError(error, dispatch)
  }
}

export const loadMoreRewards = lastId => async dispatch => {
  try {
    const { data } = await request.get(
      `${API_URL}/more/rewards?lastId=${lastId}`,
      auth()
    )
    dispatch({
      type: NOTI.LOAD_MORE_REWARDS,
      data
    })
    return Promise.resolve()
  } catch (error) {
    console.error(error.response || error)
    handleError(error, dispatch)
  }
}

export const increaseNumNewNotis = () => ({
  type: NOTI.INCREASE_NUM_NEW_NOTIS
})

export const increaseNumNewPosts = () => ({
  type: NOTI.INCREASE_NUM_NEW_POSTS
})

export const notifyChatSubjectChange = subject => ({
  type: NOTI.CHAT_SUBJECT_CHANGE,
  subject
})

export const resetNumNewPosts = () => ({
  type: NOTI.RESET_NUM_NEW_POSTS
})
<commit_msg>last active added<commit_after>import request from 'axios'
import { auth, handleError } from '../constants'
import { URL } from 'constants/URL'
import NOTI from '../constants/Noti'

const API_URL = `${URL}/notification`
const appVersion = '0.1.16'

export const checkVersion = () => async dispatch => {
  try {
    const { data } = await request.get(
      `${API_URL}/version?version=${appVersion}`
    )
    dispatch({
      type: NOTI.CHECK_VERSION,
      data
    })
  } catch (error) {
    console.error(error.response || error)
    handleError(error, dispatch)
  }
}

export const clearRewards = () => ({
  type: NOTI.CLEAR_REWARDS
})

export const clearNotifications = () => ({
  type: NOTI.CLEAR
})

export const fetchNotifications = () => async dispatch => {
  try {
    if (auth().headers.authorization === null) {
      const { data } = await request.get(`${API_URL}/chatSubject`)
      dispatch({
        type: NOTI.LOAD,
        data: {
          notifications: [],
          rewards: [],
          totalRewardAmount: 0,
          currentChatSubject: data
        }
      })
    } else {
      const { data } = await request.get(API_URL, auth())
      dispatch({
        type: NOTI.LOAD,
        data
      })
    }
    return Promise.resolve()
  } catch (error) {
    console.error(error.response || error)
    handleError(error, dispatch)
  }
}

export const loadMoreNotifications = lastId => async dispatch => {
  try {
    const { data } = await request.get(
      `${API_URL}/more?lastId=${lastId}`,
      auth()
    )
    dispatch({
      type: NOTI.LOAD_MORE,
      data
    })
    return Promise.resolve()
  } catch (error) {
    console.error(error.response || error)
    handleError(error, dispatch)
  }
}

export const loadMoreRewards = lastId => async dispatch => {
  try {
    const { data } = await request.get(
      `${API_URL}/more/rewards?lastId=${lastId}`,
      auth()
    )
    dispatch({
      type: NOTI.LOAD_MORE_REWARDS,
      data
    })
    return Promise.resolve()
  } catch (error) {
    console.error(error.response || error)
    handleError(error, dispatch)
  }
}

export const increaseNumNewNotis = () => ({
  type: NOTI.INCREASE_NUM_NEW_NOTIS
})

export const increaseNumNewPosts = () => ({
  type: NOTI.INCREASE_NUM_NEW_POSTS
})

export const notifyChatSubjectChange = subject => ({
  type: NOTI.CHAT_SUBJECT_CHANGE,
  subject
})

export const resetNumNewPosts = () => ({
  type: NOTI.RESET_NUM_NEW_POSTS
})
<|endoftext|>


<commit_before>$spec.describe('my awesome addition function', function(spec) {

    var add = function() {
       var total = 0;
       for (var i = 0, l = arguments.length; i < l; i++) {
           total += arguments[i];
       }
       return total;
    };

    spec.before(function() {
        // don't need to set anything up this time
    });

    spec.it('adds two numbers', function(expect) {
        expect(add(2,2)).to.equal(4);
    });

    spec.it('adds three numbers', function(expect) {
        expect(add(1,1,2)).to.equal(4);
    });

    // to show a failing spec
    spec.it('adds two numbers', function(expect) {
        expect(add(1,1,2)).to.equal(5);
    });

    // to show a pending spec
    spec.it('casts and adds strings');
});<commit_msg>Updating addition example to mirror blog post<commit_after>$spec.describe('my awesome addition function', function(spec) {

    var add = function() {
       var total = 0;
       for (var i = 0, l = arguments.length; i < l; i++) {
           total += arguments[i];
       }
       return total;
    };

    spec.before(function() {
        // code in this block is run before each spec
    });

    spec.it('adds two numbers', function(expect) {
        expect(add(2,2)).to.equal(4);
    });

    spec.it('adds three numbers', function(expect) {
        expect(add(1,1,2)).to.equal(4);
    });

    // to show a failing spec
    spec.it('adds two numbers', function(expect) {
        expect(add(1,1,2)).to.equal(5);
    });

    // to show a pending spec
    spec.it('casts and adds strings');
});<|endoftext|>


<commit_before>/* global MutationObserver */

var registerComponent = require('../core/component').registerComponent;
var THREE = require('../lib/three');
var utils = require('../utils/');

var warn = utils.debug('components:raycaster:warn');

// Defines selectors that should be 'safe' for the MutationObserver used to
// refresh the whitelist. Matches classnames, IDs, and presence of attributes.
// Selectors for the value of an attribute, like [position=0 2 0], cannot be
// reliably detected and are therefore disallowed.
var OBSERVER_SELECTOR_RE = /^[\w\s-.,[\]#]*$/;

// Configuration for the MutationObserver used to refresh the whitelist.
// Listens for addition/removal of elements and attributes within the scene.
var OBSERVER_CONFIG = {
  childList: true,
  attributes: true,
  subtree: true
};

/**
 * Raycaster component.
 *
 * Pass options to three.js Raycaster including which objects to test.
 * Poll for intersections.
 * Emit event on origin entity and on target entity on intersect.
 *
 * @member {array} intersectedEls - List of currently intersected entities.
 * @member {array} objects - Cached list of meshes to intersect.
 * @member {number} prevCheckTime - Previous time intersection was checked. To help interval.
 * @member {object} raycaster - three.js Raycaster.
 */
module.exports.Component = registerComponent('raycaster', {
  schema: {
    autoRefresh: {default: true},
    direction: {type: 'vec3', default: {x: 0, y: 0, z: -1}},
    enabled: {default: true},
    far: {default: 1000},
    interval: {default: 100},
    near: {default: 0},
    objects: {default: ''},
    origin: {type: 'vec3'},
    recursive: {default: true},
    showLine: {default: false},
    useWorldCoordinates: {default: false}
  },

  init: function () {
    // Calculate unit vector for line direction. Can be multiplied via scalar to performantly
    // adjust line length.
    this.clearedIntersectedEls = [];
    this.unitLineEndVec3 = new THREE.Vector3();
    this.intersectedEls = [];
    this.newIntersectedEls = [];
    this.newIntersections = [];
    this.objects = [];
    this.prevCheckTime = undefined;
    this.prevIntersectedEls = [];
    this.raycaster = new THREE.Raycaster();
    this.updateOriginDirection();
    this.setDirty = this.setDirty.bind(this);
    this.observer = new MutationObserver(this.setDirty);
    this.dirty = true;
    this.lineEndVec3 = new THREE.Vector3();
    this.otherLineEndVec3 = new THREE.Vector3();
    this.lineData = {end: this.lineEndVec3};

    this.intersectedClearedDetail = {el: this.el};
    this.intersectionClearedDetail = {clearedEls: this.clearedIntersectedEls};
  },

  /**
   * Create or update raycaster object.
   */
  update: function (oldData) {
    var data = this.data;
    var el = this.el;
    var raycaster = this.raycaster;

    // Set raycaster properties.
    raycaster.far = data.far;
    raycaster.near = data.near;

    // Draw line.
    if (data.showLine &&
        (data.far !== oldData.far || data.origin !== oldData.origin ||
         data.direction !== oldData.direction || !oldData.showLine)) {
      this.unitLineEndVec3.copy(data.origin).add(data.direction).normalize();
      this.drawLine();
    }

    if (!data.showLine && oldData.showLine) {
      el.removeAttribute('line');
    }

    if (data.objects !== oldData.objects && !OBSERVER_SELECTOR_RE.test(data.objects)) {
      warn('Selector "' + data.objects + '" may not update automatically with DOM changes.');
    }

    if (data.autoRefresh !== oldData.autoRefresh && el.isPlaying) {
      data.autoRefresh
        ? this.addEventListeners()
        : this.removeEventListeners();
    }

    this.setDirty();
  },

  play: function () {
    this.addEventListeners();
  },

  pause: function () {
    this.removeEventListeners();
  },

  remove: function () {
    if (this.data.showLine) {
      this.el.removeAttribute('line');
    }
  },

  addEventListeners: function () {
    if (!this.data.autoRefresh) { return; }
    this.observer.observe(this.el.sceneEl, OBSERVER_CONFIG);
    this.el.sceneEl.addEventListener('object3dset', this.setDirty);
    this.el.sceneEl.addEventListener('object3dremove', this.setDirty);
  },

  removeEventListeners: function () {
    this.observer.disconnect();
    this.el.sceneEl.removeEventListener('object3dset', this.setDirty);
    this.el.sceneEl.removeEventListener('object3dremove', this.setDirty);
  },

  /**
   * Mark the object list as dirty, to be refreshed before next raycast.
   */
  setDirty: function () {
    this.dirty = true;
  },

  /**
   * Update list of objects to test for intersection.
   */
  refreshObjects: function () {
    var data = this.data;
    // If objects not defined, intersect with everything.
    var els = data.objects
      ? this.el.sceneEl.querySelectorAll(data.objects)
      : this.el.sceneEl.children;
    this.objects = flattenChildrenShallow(els);
    this.dirty = false;
  },

  /**
   * Check for intersections and cleared intersections on an interval.
   */
  tick: function (time) {
    var data = this.data;
    var prevCheckTime = this.prevCheckTime;

    // Only check for intersection if interval time has passed.
    if (prevCheckTime && (time - prevCheckTime < data.interval)) { return; }

    // Update check time.
    this.prevCheckTime = time;
    this.checkIntersections();
  },

  /**
   * Raycast for intersections and emit events for current and cleared inersections.
   */
  checkIntersections: (function () {
    var intersections = [];

    return function () {
      var clearedIntersectedEls = this.clearedIntersectedEls;
      var el = this.el;
      var data = this.data;
      var i;
      var intersectedEls = this.intersectedEls;
      var intersection;
      var lineLength;
      var newIntersectedEls = this.newIntersectedEls;
      var newIntersections = this.newIntersections;
      var prevIntersectedEls = this.prevIntersectedEls;
      var rawIntersections;
      var self = this;

      if (!this.data.enabled) { return; }

      // Refresh the object whitelist if needed.
      if (this.dirty) { this.refreshObjects(); }

      // Store old previously intersected entities.
      copyArray(this.prevIntersectedEls, this.intersectedEls);

      // Raycast.
      this.updateOriginDirection();
      rawIntersections = this.raycaster.intersectObjects(this.objects, data.recursive);

      // Only keep intersections against objects that have a reference to an entity.
      intersections.length = 0;
      intersectedEls.length = 0;
      for (i = 0; i < rawIntersections.length; i++) {
        intersection = rawIntersections[i];
        // Don't intersect with own line.
        if (data.showLine && intersection.object === el.getObject3D('line')) {
          continue;
        }
        if (intersection.object.el) {
          intersections.push(intersection);
          intersectedEls.push(intersection.object.el);
        }
      }

      // Get newly intersected entities.
      newIntersections.length = 0;
      newIntersectedEls.length = 0;
      for (i = 0; i < intersections.length; i++) {
        if (prevIntersectedEls.indexOf(intersections[i].object.el) === -1) {
          newIntersections.push(intersections[i]);
          newIntersectedEls.push(intersections[i].object.el);
        }
      }

      // Emit intersection cleared on both entities per formerly intersected entity.
      clearedIntersectedEls.length = 0;
      for (i = 0; i < prevIntersectedEls.length; i++) {
        if (intersectedEls.indexOf(prevIntersectedEls[i]) !== -1) { continue; }
        prevIntersectedEls[i].emit('raycaster-intersected-cleared',
                                   this.intersectedClearedDetail);
        clearedIntersectedEls.push(prevIntersectedEls[i]);
      }
      if (clearedIntersectedEls.length) {
        el.emit('raycaster-intersection-cleared', this.intersectionClearedDetail);
      }

      // Emit intersected on intersected entity per intersected entity.
      for (i = 0; i < newIntersectedEls.length; i++) {
        newIntersectedEls[i].emit('raycaster-intersected', {
          el: el,
          intersection: newIntersections[i]
        });
      }

      // Emit all intersections at once on raycasting entity.
      if (newIntersections.length) {
        el.emit('raycaster-intersection', {
          els: newIntersectedEls,
          intersections: newIntersections
        });
      }

      // Update line length.
      setTimeout(function () {
        if (self.data.showLine) {
          if (intersections.length) {
            if (intersections[0].object.el === el && intersections[1]) {
              lineLength = intersections[1].distance;
            } else {
              lineLength = intersections[0].distance;
            }
          }
          self.drawLine(lineLength);
        }
      });
    };
  })(),

  /**
   * Update origin and direction of raycaster using entity transforms and supplied origin or
   * direction offsets.
   */
  updateOriginDirection: (function () {
    var direction = new THREE.Vector3();
    var originVec3 = new THREE.Vector3();

    // Closure to make quaternion/vector3 objects private.
    return function updateOriginDirection () {
      var el = this.el;
      var data = this.data;

      if (data.useWorldCoordinates) {
        this.raycaster.set(data.origin, data.direction);
        return;
      }

      // Grab the position and rotation.
      el.object3D.updateMatrixWorld();
      el.object3D.getWorldPosition(originVec3);

      // If non-zero origin, translate the origin into world space.
      if (data.origin.x !== 0 || data.origin.y !== 0 || data.origin.z !== 0) {
        originVec3 = el.object3D.localToWorld(originVec3.copy(data.origin));
      }

      // three.js raycaster direction is relative to 0, 0, 0 NOT the origin / offset we
      // provide. Apply the offset to the direction, then rotation from the object,
      // and normalize.
      direction.copy(data.direction).transformDirection(el.object3D.matrixWorld).normalize();

      // Apply offset and direction, in world coordinates.
      this.raycaster.set(originVec3, direction);
    };
  })(),

  /**
   * Create or update line to give raycaster visual representation.
   * Customize the line through through line component.
   * We draw the line in the raycaster component to customize the line to the
   * raycaster's origin, direction, and far.
   *
   * Unlike the raycaster, we create the line as a child of the object. The line will
   * be affected by the transforms of the objects, so we don't have to calculate transforms
   * like we do with the raycaster.
   *
   * @param {number} length - Length of line. Pass in to shorten the line to the intersection
   *   point. If not provided, length will default to the max length, `raycaster.far`.
   */
  drawLine: function (length) {
    var data = this.data;
    var el = this.el;
    var endVec3;

    // Switch each time vector so line update triggered and to avoid unnecessary vector clone.
    endVec3 = this.lineData.end === this.lineEndVec3
      ? this.otherLineEndVec3
      : this.lineEndVec3;

    // Treat Infinity as 1000m for the line.
    if (length === undefined) {
      length = data.far === Infinity ? 1000 : data.far;
    }

    // Update the length of the line if given. `unitLineEndVec3` is the direction
    // given by data.direction, then we apply a scalar to give it a length.
    this.lineData.start = data.origin;
    this.lineData.end = endVec3.copy(this.unitLineEndVec3).multiplyScalar(length);
    el.setAttribute('line', this.lineData);
  }
});

/**
 * Returns children of each element's object3D group. Children are flattened
 * by one level, removing the THREE.Group wrapper, so that non-recursive
 * raycasting remains useful.
 *
 * @param  {Array<Element>} els
 * @return {Array<THREE.Object3D>}
 */
function flattenChildrenShallow (els) {
  var groups = [];
  var objects = [];
  var children;
  var i;

  // Push meshes onto list of objects to intersect.
  for (i = 0; i < els.length; i++) {
    if (els[i].object3D) {
      groups.push(els[i].object3D);
    }
  }

  // Each entity's root is a THREE.Group. Return the group's chilrden.
  for (i = 0; i < groups.length; i++) {
    children = groups[i].children;
    if (children && children.length) {
      objects.push.apply(objects, children);
    }
  }

  return objects;
}

/**
 * Copy contents of one array to another without allocating new array.
 */
function copyArray (a, b) {
  var i;
  a.length = b.length;
  for (i = 0; i < b.length; i++) {
    a[i] = b[i];
  }
}
<commit_msg>expose raycaster.intersections array<commit_after>/* global MutationObserver */

var registerComponent = require('../core/component').registerComponent;
var THREE = require('../lib/three');
var utils = require('../utils/');

var warn = utils.debug('components:raycaster:warn');

// Defines selectors that should be 'safe' for the MutationObserver used to
// refresh the whitelist. Matches classnames, IDs, and presence of attributes.
// Selectors for the value of an attribute, like [position=0 2 0], cannot be
// reliably detected and are therefore disallowed.
var OBSERVER_SELECTOR_RE = /^[\w\s-.,[\]#]*$/;

// Configuration for the MutationObserver used to refresh the whitelist.
// Listens for addition/removal of elements and attributes within the scene.
var OBSERVER_CONFIG = {
  childList: true,
  attributes: true,
  subtree: true
};

/**
 * Raycaster component.
 *
 * Pass options to three.js Raycaster including which objects to test.
 * Poll for intersections.
 * Emit event on origin entity and on target entity on intersect.
 *
 * @member {array} intersectedEls - List of currently intersected entities.
 * @member {array} objects - Cached list of meshes to intersect.
 * @member {number} prevCheckTime - Previous time intersection was checked. To help interval.
 * @member {object} raycaster - three.js Raycaster.
 */
module.exports.Component = registerComponent('raycaster', {
  schema: {
    autoRefresh: {default: true},
    direction: {type: 'vec3', default: {x: 0, y: 0, z: -1}},
    enabled: {default: true},
    far: {default: 1000},
    interval: {default: 100},
    near: {default: 0},
    objects: {default: ''},
    origin: {type: 'vec3'},
    recursive: {default: true},
    showLine: {default: false},
    useWorldCoordinates: {default: false}
  },

  init: function () {
    this.clearedIntersectedEls = [];
    this.unitLineEndVec3 = new THREE.Vector3();
    this.intersectedEls = [];
    this.intersections = [];
    this.newIntersectedEls = [];
    this.newIntersections = [];
    this.objects = [];
    this.prevCheckTime = undefined;
    this.prevIntersectedEls = [];
    this.raycaster = new THREE.Raycaster();
    this.updateOriginDirection();
    this.setDirty = this.setDirty.bind(this);
    this.observer = new MutationObserver(this.setDirty);
    this.dirty = true;
    this.lineEndVec3 = new THREE.Vector3();
    this.otherLineEndVec3 = new THREE.Vector3();
    this.lineData = {end: this.lineEndVec3};

    this.intersectedClearedDetail = {el: this.el};
    this.intersectionClearedDetail = {clearedEls: this.clearedIntersectedEls};
  },

  /**
   * Create or update raycaster object.
   */
  update: function (oldData) {
    var data = this.data;
    var el = this.el;
    var raycaster = this.raycaster;

    // Set raycaster properties.
    raycaster.far = data.far;
    raycaster.near = data.near;

    // Draw line.
    if (data.showLine &&
        (data.far !== oldData.far || data.origin !== oldData.origin ||
         data.direction !== oldData.direction || !oldData.showLine)) {
      // Calculate unit vector for line direction. Can be multiplied via scalar to performantly
      // adjust line length.
      this.unitLineEndVec3.copy(data.origin).add(data.direction).normalize();
      this.drawLine();
    }

    if (!data.showLine && oldData.showLine) {
      el.removeAttribute('line');
    }

    if (data.objects !== oldData.objects && !OBSERVER_SELECTOR_RE.test(data.objects)) {
      warn('Selector "' + data.objects + '" may not update automatically with DOM changes.');
    }

    if (data.autoRefresh !== oldData.autoRefresh && el.isPlaying) {
      data.autoRefresh
        ? this.addEventListeners()
        : this.removeEventListeners();
    }

    this.setDirty();
  },

  play: function () {
    this.addEventListeners();
  },

  pause: function () {
    this.removeEventListeners();
  },

  remove: function () {
    if (this.data.showLine) {
      this.el.removeAttribute('line');
    }
  },

  addEventListeners: function () {
    if (!this.data.autoRefresh) { return; }
    this.observer.observe(this.el.sceneEl, OBSERVER_CONFIG);
    this.el.sceneEl.addEventListener('object3dset', this.setDirty);
    this.el.sceneEl.addEventListener('object3dremove', this.setDirty);
  },

  removeEventListeners: function () {
    this.observer.disconnect();
    this.el.sceneEl.removeEventListener('object3dset', this.setDirty);
    this.el.sceneEl.removeEventListener('object3dremove', this.setDirty);
  },

  /**
   * Mark the object list as dirty, to be refreshed before next raycast.
   */
  setDirty: function () {
    this.dirty = true;
  },

  /**
   * Update list of objects to test for intersection.
   */
  refreshObjects: function () {
    var data = this.data;
    // If objects not defined, intersect with everything.
    var els = data.objects
      ? this.el.sceneEl.querySelectorAll(data.objects)
      : this.el.sceneEl.children;
    this.objects = flattenChildrenShallow(els);
    this.dirty = false;
  },

  /**
   * Check for intersections and cleared intersections on an interval.
   */
  tick: function (time) {
    var data = this.data;
    var prevCheckTime = this.prevCheckTime;

    // Only check for intersection if interval time has passed.
    if (prevCheckTime && (time - prevCheckTime < data.interval)) { return; }

    // Update check time.
    this.prevCheckTime = time;
    this.checkIntersections();
  },

  /**
   * Raycast for intersections and emit events for current and cleared inersections.
   */
  checkIntersections: function () {
    var clearedIntersectedEls = this.clearedIntersectedEls;
    var el = this.el;
    var data = this.data;
    var i;
    var intersectedEls = this.intersectedEls;
    var intersection;
    var intersections = this.intersections;
    var lineLength;
    var newIntersectedEls = this.newIntersectedEls;
    var newIntersections = this.newIntersections;
    var prevIntersectedEls = this.prevIntersectedEls;
    var rawIntersections;
    var self = this;

    if (!this.data.enabled) { return; }

    // Refresh the object whitelist if needed.
    if (this.dirty) { this.refreshObjects(); }

    // Store old previously intersected entities.
    copyArray(this.prevIntersectedEls, this.intersectedEls);

    // Raycast.
    this.updateOriginDirection();
    rawIntersections = this.raycaster.intersectObjects(this.objects, data.recursive);

    // Only keep intersections against objects that have a reference to an entity.
    intersections.length = 0;
    intersectedEls.length = 0;
    for (i = 0; i < rawIntersections.length; i++) {
      intersection = rawIntersections[i];
      // Don't intersect with own line.
      if (data.showLine && intersection.object === el.getObject3D('line')) {
        continue;
      }
      if (intersection.object.el) {
        intersections.push(intersection);
        intersectedEls.push(intersection.object.el);
      }
    }

    // Get newly intersected entities.
    newIntersections.length = 0;
    newIntersectedEls.length = 0;
    for (i = 0; i < intersections.length; i++) {
      if (prevIntersectedEls.indexOf(intersections[i].object.el) === -1) {
        newIntersections.push(intersections[i]);
        newIntersectedEls.push(intersections[i].object.el);
      }
    }

    // Emit intersection cleared on both entities per formerly intersected entity.
    clearedIntersectedEls.length = 0;
    for (i = 0; i < prevIntersectedEls.length; i++) {
      if (intersectedEls.indexOf(prevIntersectedEls[i]) !== -1) { continue; }
      prevIntersectedEls[i].emit('raycaster-intersected-cleared',
                                 this.intersectedClearedDetail);
      clearedIntersectedEls.push(prevIntersectedEls[i]);
    }
    if (clearedIntersectedEls.length) {
      el.emit('raycaster-intersection-cleared', this.intersectionClearedDetail);
    }

    // Emit intersected on intersected entity per intersected entity.
    for (i = 0; i < newIntersectedEls.length; i++) {
      newIntersectedEls[i].emit('raycaster-intersected', {
        el: el,
        intersection: newIntersections[i]
      });
    }

    // Emit all intersections at once on raycasting entity.
    if (newIntersections.length) {
      el.emit('raycaster-intersection', {
        els: newIntersectedEls,
        intersections: newIntersections
      });
    }

    // Update line length.
    setTimeout(function () {
      if (self.data.showLine) {
        if (intersections.length) {
          if (intersections[0].object.el === el && intersections[1]) {
            lineLength = intersections[1].distance;
          } else {
            lineLength = intersections[0].distance;
          }
        }
        self.drawLine(lineLength);
      }
    });
  },

  /**
   * Update origin and direction of raycaster using entity transforms and supplied origin or
   * direction offsets.
   */
  updateOriginDirection: (function () {
    var direction = new THREE.Vector3();
    var originVec3 = new THREE.Vector3();

    // Closure to make quaternion/vector3 objects private.
    return function updateOriginDirection () {
      var el = this.el;
      var data = this.data;

      if (data.useWorldCoordinates) {
        this.raycaster.set(data.origin, data.direction);
        return;
      }

      // Grab the position and rotation.
      el.object3D.updateMatrixWorld();
      el.object3D.getWorldPosition(originVec3);

      // If non-zero origin, translate the origin into world space.
      if (data.origin.x !== 0 || data.origin.y !== 0 || data.origin.z !== 0) {
        originVec3 = el.object3D.localToWorld(originVec3.copy(data.origin));
      }

      // three.js raycaster direction is relative to 0, 0, 0 NOT the origin / offset we
      // provide. Apply the offset to the direction, then rotation from the object,
      // and normalize.
      direction.copy(data.direction).transformDirection(el.object3D.matrixWorld).normalize();

      // Apply offset and direction, in world coordinates.
      this.raycaster.set(originVec3, direction);
    };
  })(),

  /**
   * Create or update line to give raycaster visual representation.
   * Customize the line through through line component.
   * We draw the line in the raycaster component to customize the line to the
   * raycaster's origin, direction, and far.
   *
   * Unlike the raycaster, we create the line as a child of the object. The line will
   * be affected by the transforms of the objects, so we don't have to calculate transforms
   * like we do with the raycaster.
   *
   * @param {number} length - Length of line. Pass in to shorten the line to the intersection
   *   point. If not provided, length will default to the max length, `raycaster.far`.
   */
  drawLine: function (length) {
    var data = this.data;
    var el = this.el;
    var endVec3;

    // Switch each time vector so line update triggered and to avoid unnecessary vector clone.
    endVec3 = this.lineData.end === this.lineEndVec3
      ? this.otherLineEndVec3
      : this.lineEndVec3;

    // Treat Infinity as 1000m for the line.
    if (length === undefined) {
      length = data.far === Infinity ? 1000 : data.far;
    }

    // Update the length of the line if given. `unitLineEndVec3` is the direction
    // given by data.direction, then we apply a scalar to give it a length.
    this.lineData.start = data.origin;
    this.lineData.end = endVec3.copy(this.unitLineEndVec3).multiplyScalar(length);
    el.setAttribute('line', this.lineData);
  }
});

/**
 * Returns children of each element's object3D group. Children are flattened
 * by one level, removing the THREE.Group wrapper, so that non-recursive
 * raycasting remains useful.
 *
 * @param  {Array<Element>} els
 * @return {Array<THREE.Object3D>}
 */
function flattenChildrenShallow (els) {
  var groups = [];
  var objects = [];
  var children;
  var i;

  // Push meshes onto list of objects to intersect.
  for (i = 0; i < els.length; i++) {
    if (els[i].object3D) {
      groups.push(els[i].object3D);
    }
  }

  // Each entity's root is a THREE.Group. Return the group's chilrden.
  for (i = 0; i < groups.length; i++) {
    children = groups[i].children;
    if (children && children.length) {
      objects.push.apply(objects, children);
    }
  }

  return objects;
}

/**
 * Copy contents of one array to another without allocating new array.
 */
function copyArray (a, b) {
  var i;
  a.length = b.length;
  for (i = 0; i < b.length; i++) {
    a[i] = b[i];
  }
}
<|endoftext|>


<commit_before>function randomNumber(min, max) {
	return Math.random() * (max - min) + min;
}

function randomBar(date, lastClose) {
	var open = randomNumber(lastClose * .95, lastClose * 1.05);
	var close = randomNumber(open * .95, open * 1.05);
	var high = randomNumber(Math.max(open, close), Math.max(open, close) * 1.1);
	var low = randomNumber(Math.min(open, close) * .9, Math.min(open, close));
	return {
		t: date.valueOf(),
		o: open,
		h: high,
		l: low,
		c: close
	};
}

var dateFormat = 'MMMM DD YYYY';
var date = moment('April 01 2017', dateFormat);
var data = [randomBar(date, 30)];
while (data.length < 60) {
	date = date.add(1, 'd');
	if (date.isoWeekday() <= 5) {
		data.push(randomBar(date, data[data.length - 1].c));
	}
}

var ctx = document.getElementById("chart1").getContext("2d");
ctx.canvas.width = 1000;
ctx.canvas.height = 300;
new Chart(ctx, {
	type: 'financial',
	data: {
		datasets: [{
			label: "NASDAQ: MSFT - Microsoft Corporation",
			data: data
		}]
	}
});
<commit_msg>Use CHRT as fake ticker symbol<commit_after>function randomNumber(min, max) {
	return Math.random() * (max - min) + min;
}

function randomBar(date, lastClose) {
	var open = randomNumber(lastClose * .95, lastClose * 1.05);
	var close = randomNumber(open * .95, open * 1.05);
	var high = randomNumber(Math.max(open, close), Math.max(open, close) * 1.1);
	var low = randomNumber(Math.min(open, close) * .9, Math.min(open, close));
	return {
		t: date.valueOf(),
		o: open,
		h: high,
		l: low,
		c: close
	};
}

var dateFormat = 'MMMM DD YYYY';
var date = moment('April 01 2017', dateFormat);
var data = [randomBar(date, 30)];
while (data.length < 60) {
	date = date.add(1, 'd');
	if (date.isoWeekday() <= 5) {
		data.push(randomBar(date, data[data.length - 1].c));
	}
}

var ctx = document.getElementById("chart1").getContext("2d");
ctx.canvas.width = 1000;
ctx.canvas.height = 300;
new Chart(ctx, {
	type: 'financial',
	data: {
		datasets: [{
			label: "CHRT - Chart.js Corporation",
			data: data
		}]
	}
});
<|endoftext|>


<commit_before>/* Magic Mirror
 * Module: MMM-Hello-Mirror
 *
 * By Mathias Kaniut
 * MIT Licensed
 */

Module.register("MMM-Hello-Mirror",{
	// Default module config.
    	defaults: {
        	language: "de",
		voice: "Deutsch Female",
		wakeUp: "Hallo (magischer) Spiegel",
		animationSpeed: 2000,
		debug: true,
		broadcastEvents: true
    	},

	// Called when all modules are loaded an the system is ready to boot up
	start: function() {
		this.textMessage = "";

		if (responsiveVoice) {
			responsiveVoice.setDefaultVoice(this.config.voice);
		}
		if (annyang) {
			// Set language for date object
			moment.locale(this.config.language);

			// Set the debug mode
			annyang.debug(this.config.debug);

			// Set the language of annyang
			annyang.setLanguage(this.config.language);

			// Define the commands
			var commands = {
				'Hallo (magischer) Spiegel *command': function(command) {
					Log.info('Voice command recognized in module ' + this.name + ': ' + command);
					if (this.config.broadcastEvents) {
						this.sendNotification("VOICE_COMMAND", command);
					}
					if (responsiveVoice) {
						responsiveVoice.speak( "Ich konnte dich verstehen" );
					}
    				}
			};

			// Add the commands to annyang
  			annyang.addCommands(commands);

			// Add callback functions for errors
			annyang.addCallback('error', function() {
				Log.error('ERROR in module ' + this.name + ': ' + 'Speech Recognition fails because an undefined error occured');
			});
			annyang.addCallback('errorNetwork', function() {
		    		Log.error('ERROR in module ' + this.name + ': ' + 'Speech Recognition fails because of a network error');
			});
			annyang.addCallback('errorPermissionBlocked', function() {
		    		Log.error('ERROR in module ' + this.name + ': ' + 'Browser blocks the permission request to use Speech Recognition');
			});
			annyang.addCallback('errorPermissionDenied', function() {
		    		Log.error('ERROR in module ' + this.name + ': ' + 'The user blocks the permission request to use Speech Recognition');
			});
			annyang.addCallback('resultNoMatch', function(phrases) {
				Log.error('ERROR in module ' + this.name + ': ' + 'No match for voice command ' + phrases);
			});
			annyang.addCallback('soundstart', function() {
				this.textMessage = this.translate("HEAR_YOU");
  				this.updateDom(this.config.animationSpeed);
			});
			annyang.addCallback('result', function() {
				this.textMessage = "";
  				this.updateDom(this.config.animationSpeed);
			});

			// Start listening
			annyang.start();

			Log.log(this.name + ' is started!');
		} else {
			Log.error('ERROR in module ' + this.name + ': ' + 'Google Speech Recognizer is down :(');
		}
	},

	// Load required additional scripts
	getScripts: function() {
		return [
			'//cdnjs.cloudflare.com/ajax/libs/annyang/2.6.0/annyang.min.js',  // annyang! SpeechRecognition
			'http://code.responsivevoice.org/responsivevoice.js', // ResponsiveVoice
			'moment.js' // Parse, validate, manipulate, and display dates in JavaScript
		];
	},

	// Define additional styles
	getStyles: function() {
		return [
			"font-awesome.css",
			this.file('css/MMM-Hello-Mirror.css')
		];
	},

	// Request translation files
	getTranslations: function() {
	    	return {
		    	en: "translations/en.json",
		    	de: "translations/de.json"
		};
	},

    	// Override dom generator.
    	getDom: function() {
        	var wrapper = document.createElement("div");
		wrapper.className = "small light";
        	wrapper.innerHTML = this.textMessage;
        	return wrapper;
    	}
});
<commit_msg>config correction<commit_after>/* Magic Mirror
 * Module: MMM-Hello-Mirror
 *
 * By Mathias Kaniut
 * MIT Licensed
 */

Module.register("MMM-Hello-Mirror",{
	// Default module config.
    defaults: {
        language: "de",
        voice: "Deutsch Female",
        wakeUp: "Hallo (magischer) Spiegel",
        animationSpeed: 2000,
        debug: true,
        broadcastEvents: true
    },

	// Called when all modules are loaded an the system is ready to boot up
	start: function() {
		this.textMessage = "";

		if (responsiveVoice) {
			responsiveVoice.setDefaultVoice(this.config.voice);
		}
		if (annyang) {
			// Set language for date object
			moment.locale(this.config.language);

			// Set the debug mode
			annyang.debug(this.config.debug);

			// Set the language of annyang
			annyang.setLanguage(this.config.language);

			// Define the commands
			var commands = {
				'Hallo (magischer) Spiegel *command': function(command) {
					Log.info('Voice command recognized in module ' + this.name + ': ' + command);
					if (this.config.broadcastEvents) {
						this.sendNotification("VOICE_COMMAND", command);
					}
					if (responsiveVoice) {
						responsiveVoice.speak( "Ich konnte dich verstehen" );
					}
    				}
			};

			// Add the commands to annyang
  			annyang.addCommands(commands);

			// Add callback functions for errors
			annyang.addCallback('error', function() {
				Log.error('ERROR in module ' + this.name + ': ' + 'Speech Recognition fails because an undefined error occured');
			});
			annyang.addCallback('errorNetwork', function() {
		    		Log.error('ERROR in module ' + this.name + ': ' + 'Speech Recognition fails because of a network error');
			});
			annyang.addCallback('errorPermissionBlocked', function() {
		    		Log.error('ERROR in module ' + this.name + ': ' + 'Browser blocks the permission request to use Speech Recognition');
			});
			annyang.addCallback('errorPermissionDenied', function() {
		    		Log.error('ERROR in module ' + this.name + ': ' + 'The user blocks the permission request to use Speech Recognition');
			});
			annyang.addCallback('resultNoMatch', function(phrases) {
				Log.error('ERROR in module ' + this.name + ': ' + 'No match for voice command ' + phrases);
			});
			annyang.addCallback('soundstart', function() {
				this.textMessage = this.translate("HEAR_YOU");
  				this.updateDom(this.config.animationSpeed);
			});
			annyang.addCallback('result', function() {
				this.textMessage = "";
  				this.updateDom(this.config.animationSpeed);
			});

			// Start listening
			annyang.start();

			Log.log(this.name + ' is started!');
		} else {
			Log.error('ERROR in module ' + this.name + ': ' + 'Google Speech Recognizer is down :(');
		}
	},

	// Load required additional scripts
	getScripts: function() {
		return [
			'//cdnjs.cloudflare.com/ajax/libs/annyang/2.6.0/annyang.min.js',  // annyang! SpeechRecognition
			'http://code.responsivevoice.org/responsivevoice.js', // ResponsiveVoice
			'moment.js' // Parse, validate, manipulate, and display dates in JavaScript
		];
	},

	// Define additional styles
	getStyles: function() {
		return [
			"font-awesome.css",
			this.file('css/MMM-Hello-Mirror.css')
		];
	},

	// Request translation files
	getTranslations: function() {
	    	return {
		    	en: "translations/en.json",
		    	de: "translations/de.json"
		};
	},

    	// Override dom generator.
    	getDom: function() {
        	var wrapper = document.createElement("div");
		wrapper.className = "small light";
        	wrapper.innerHTML = this.textMessage;
        	return wrapper;
    	}
});
<|endoftext|>


<commit_before>var url = require('url');
var redis = require('redis');

if (process.env.REDISTOGO_URL) {
  var rtg   = url.parse(process.env.REDISTOGO_URL);
  var client = redis.createClient(rtg.port, rtg.hostname);
  redis.auth(rtg.auth.split(":")[1]);
} else {
  var client = redis.createClient();
}

module.exports = client;<commit_msg>Fix misnamed variable<commit_after>var url = require('url');
var redis = require('redis');

if (process.env.REDISTOGO_URL) {
  var rtg   = url.parse(process.env.REDISTOGO_URL);
  var client = redis.createClient(rtg.port, rtg.hostname);
  client.auth(rtg.auth.split(":")[1]);
} else {
  var client = redis.createClient();
}

module.exports = client;<|endoftext|>


<commit_before>/**
 * The router module.
 *
 * Router handles app routing and URL parameters and updates Presenter.
 *
 * @return singleton instance of Router class (extends Backbone.Router).
 */
define([
  'underscore',
  'backbone',
  'amplify',
  'map/utils',
  'map/services/PlaceService'
], function(_, Backbone, amplify, utils, PlaceService) {

  'use strict';

  var Router = Backbone.Router.extend({

    routes: {
      'map(/:zoom)(/:lat)(/:lng)(/:iso)(/:maptype)(/:baselayers)(/:sublayers)(/)': 'map',
      'embed/map(/:zoom)(/:lat)(/:lng)(/:iso)(/:maptype)(/:baselayers)(/:sublayers)(/)': 'embed'
    },

    /**
     * Boot file:
     *
     * @param  {[type]} boot [description]
     */
    initialize: function(mainView) {
      this.bind('all', this._checkForCacheBust());
      this.name = null;
      this.mainView = mainView;
      this.placeService = new PlaceService(this);
    },

    map: function() {
      this.name = 'map';
      this.mainView.setMapMode();
      this.initMap.apply(this, arguments);
    },

    embed: function() {
      this.name = 'embed/map';
      this.initMap.apply(this, arguments);
    },

    initMap: function(zoom, lat, lng, iso, maptype, baselayers, sublayers) {
      var params = _.extend({
        zoom: zoom,
        lat: lat,
        lng: lng,
        iso: iso,
        maptype: maptype,
        baselayers: baselayers,
        sublayers: sublayers
      }, _.parseUrl());

      this.placeService.initPlace(this.name, params);
    },

    /**
     * If the URL contains the cache parameter (e.g., cache=bust), clear all
     * cached values in the browser (e.g., from memory, local storage,
     * session).
     */
    _checkForCacheBust: function() {
      var params = _.parseUrl();

      if (_.has(params, 'cache')) {
        _.each(amplify.store(), function(value, key) {
          amplify.store(key, null);
        });
      }
    },

    navigateTo: function(route, options) {
      this.navigate(route, options);
    }

  });

  return Router;

});
<commit_msg>cache<commit_after>/**
 * The router module.
 *
 * Router handles app routing and URL parameters and updates Presenter.
 *
 * @return singleton instance of Router class (extends Backbone.Router).
 */
define([
  'underscore',
  'backbone',
  'amplify',
  'map/utils',
  'map/services/PlaceService'
], function(_, Backbone, amplify, utils, PlaceService) {

  'use strict';

  var Router = Backbone.Router.extend({

    // temporary, we will do it with env variables
    _cacheVersion: 0,

    routes: {
      'map(/:zoom)(/:lat)(/:lng)(/:iso)(/:maptype)(/:baselayers)(/:sublayers)(/)': 'map',
      'embed/map(/:zoom)(/:lat)(/:lng)(/:iso)(/:maptype)(/:baselayers)(/:sublayers)(/)': 'embed'
    },

    /**
     * Boot file:
     *
     * @param  {[type]} boot [description]
     */
    initialize: function(mainView) {
      this.bind('all', this._checkForCacheBust());
      this.name = null;
      this.mainView = mainView;
      this.placeService = new PlaceService(this);
    },

    map: function() {
      this.name = 'map';
      this.mainView.setMapMode();
      this.initMap.apply(this, arguments);
    },

    embed: function() {
      this.name = 'embed/map';
      this.initMap.apply(this, arguments);
    },

    initMap: function(zoom, lat, lng, iso, maptype, baselayers, sublayers) {
      var params = _.extend({
        zoom: zoom,
        lat: lat,
        lng: lng,
        iso: iso,
        maptype: maptype,
        baselayers: baselayers,
        sublayers: sublayers
      }, _.parseUrl());

      this.placeService.initPlace(this.name, params);
    },

    /**
     * If the URL contains the cache parameter (e.g., cache=bust), clear all
     * cached values in the browser (e.g., from memory, local storage,
     * session).
     */
    _checkForCacheBust: function() {
      var params = _.parseUrl();
      var localCacheVersion = _.toNumber(
        localStorage.getItem('CACHE_VERSION'));

      if (_.has(params, 'cache') || localCacheVersion !== this._cacheVersion) {
        console.log('Local cache deleted');
        _.each(amplify.store(), function(value, key) {
          amplify.store(key, null);
        });

        localStorage.setItem('CACHE_VERSION', this._cacheVersion);
      }
    },

    navigateTo: function(route, options) {
      this.navigate(route, options);
    }

  });

  return Router;

});
<|endoftext|>


<commit_before>var updateTodo = function(id, isDone){
  $.ajax({
    url: '/graphql?query=mutation+_{updateTodo(id:"' + id + '",done:' + isDone + '){id,text,done}}'
  }).done(function(data) {
    console.log(data);
    var dataParsed = JSON.parse(data);
    var updatedTodo = dataParsed.data.updateTodo;
    if (updatedTodo.done) {
      $('#' + updatedTodo.id).parent().parent().addClass('todo-done');
    } else {
      $('#' + updatedTodo.id).parent().parent().removeClass('todo-done');
    }
  });
};

var handleTodoList = function(object) {
  var todos = object;

  if (!todos.length) {
    $('.todo-list-container').append('
There are no tasks for you today
');
  }

  $.each(todos, function(i, v) {
    var doneHtml = '<input id="' + v.id + '" type="checkbox"' + (v.done ? ' checked="checked"' : '') + '>';
    var labelHtml = '' + doneHtml + ' ' + v.text + '';
    var itemHtml = '
' + labelHtml + '
';

    $('.todo-list-container').append(itemHtml);
    $('#' + v.id).click(function(){
      var id = $(this).prop('id');
      var isDone = $(this).prop('checked');
      updateTodo(id, isDone);
    });
  });
};

var loadTodos = function() {
  $.ajax({
    url: "/graphql?query={todoList{id,text,done}}"
  }).done(function(data) {
    console.log(data);
    var dataParsed = JSON.parse(data);
    handleTodoList(dataParsed.data.todoList);
  });
};

var addTodo = function(todoText) {
  if (!todoText || todoText === "") {
    alert('Please specify a task');
    return;
  }

  $.ajax({
    url: '/graphql?query=mutation+_{createTodo(text:"' + todoText + '"){id,text,done}}'
  }).done(function(data) {
    console.log(data);
    var dataParsed = JSON.parse(data);
    var todoList = [dataParsed.data.createTodo];
    handleTodoList(todoList);
  });
};

$(document).ready(function() {
  $('.todo-add-form').submit(function(e){
    e.preventDefault();
    addTodo($('.todo-add-form #task').val());
    $('.todo-add-form #task').val('');
  });

  loadTodos();
});
<commit_msg>Adjust the app js to use the template. Much more readable<commit_after>var updateTodo = function(id, isDone){
  $.ajax({
    url: '/graphql?query=mutation+_{updateTodo(id:"' + id + '",done:' + isDone + '){id,text,done}}'
  }).done(function(data) {
    console.log(data);
    var dataParsed = JSON.parse(data);
    var updatedTodo = dataParsed.data.updateTodo;
    if (updatedTodo.done) {
      $('#' + updatedTodo.id).parent().parent().parent().addClass('todo-done');
    } else {
      $('#' + updatedTodo.id).parent().parent().parent().removeClass('todo-done');
    }
  });
};

var handleTodoList = function(object) {
  var todos = object;

  if (!todos.length) {
    $('.todo-list-container').append('
There are no tasks for you today
');
    return
  } else {
    $('.todo-list-container').empty();
  }

  $.each(todos, function(i, v) {
    var todoTemplate = $('#todoItemTemplate').html();
    var todo = todoTemplate.replace('{{todo-id}}', v.id);
    todo = todo.replace('{{todo-text}}', v.text);
    todo = todo.replace('{{todo-checked}}', (v.done ? ' checked="checked"' : ''));
    todo = todo.replace('{{todo-done}}', (v.done ? ' todo-done' : ''));

    $('.todo-list-container').append(todo);
    $('#' + v.id).click(function(){
      var id = $(this).prop('id');
      var isDone = $(this).prop('checked');
      updateTodo(id, isDone);
    });
  });
};

var loadTodos = function() {
  $.ajax({
    url: "/graphql?query={todoList{id,text,done}}"
  }).done(function(data) {
    console.log(data);
    var dataParsed = JSON.parse(data);
    handleTodoList(dataParsed.data.todoList);
  });
};

var addTodo = function(todoText) {
  if (!todoText || todoText === "") {
    alert('Please specify a task');
    return;
  }

  $.ajax({
    url: '/graphql?query=mutation+_{createTodo(text:"' + todoText + '"){id,text,done}}'
  }).done(function(data) {
    console.log(data);
    var dataParsed = JSON.parse(data);
    var todoList = [dataParsed.data.createTodo];
    handleTodoList(todoList);
  });
};

$(document).ready(function() {
  $('.todo-add-form').submit(function(e){
    e.preventDefault();
    addTodo($('.todo-add-form #task').val());
    $('.todo-add-form #task').val('');
  });

  loadTodos();
});
<|endoftext|>


<commit_before>module.exports = {
  debug: true,
  branch: 'dist',
  verifyConditions: [
    '@semantic-release/changelog',
    '@semantic-release/npm',
    '@semantic-release/github',
  ],
  prepare: [
    '@semantic-release/changelog',
    '@semantic-release/npm',
    '@semantic-release/git',
  ],
  publish: [
    {
      'path': '@semantic-release/exec',
      'cmd': 'node tools/build-dist ${nextRelease.version}'
    },
    '@semantic-release/npm',
    '@semantic-release/github',
  ],
  success: [
    '@semantic-release/github',
    {
      'path': '@semantic-release/exec',
      'cmd': 'node tools/cherry-pick-release-to-master'
    },
  ]
}
<commit_msg>fix(semantic-release): move build-dist to prepare<commit_after>module.exports = {
  debug: true,
  branch: 'dist',
  verifyConditions: [
    '@semantic-release/changelog',
    '@semantic-release/npm',
    '@semantic-release/github',
  ],
  prepare: [
    {
      'path': '@semantic-release/exec',
      'cmd': 'node tools/build-dist ${nextRelease.version}'
    },
    '@semantic-release/changelog',
    '@semantic-release/npm',
    '@semantic-release/git',
  ],
  publish: [
    '@semantic-release/npm',
    '@semantic-release/github',
  ],
  success: [
    '@semantic-release/github',
    {
      'path': '@semantic-release/exec',
      'cmd': 'node tools/cherry-pick-release-to-master'
    },
  ]
}
<|endoftext|>


<commit_before>const app = require('electron').remote.app
const path = require('path')
var assert = require('assert')
let webRoot = path.dirname(__dirname)
let model = require(path.join(webRoot, 'app', 'model.js'))

// console.log('app', app)

describe('Models', function() {

	before(function() {
		// runs before all tests in this block
		// model.wipeDatabase(app.getPath('userData'), function() {
			model.initDb(app.getPath('userData'));
		// });
	});

	describe('Questions', function() {
		describe('getQuestions()', function() {
			it('should return all questions', function() {
				console.log("model", model.getQuestions());
			})
		})
	})

})
<commit_msg>sample test not working<commit_after>const app = require('electron').remote.app
const path = require('path')
var assert = require('assert')
let webRoot = path.dirname(__dirname)
let model = require(path.join(webRoot, 'app', 'model.js'))

// console.log('app', app)

describe('Models', function() {

	// before(function() {
	// 	// runs before all tests in this block
	// 	// model.wipeDatabase(app.getPath('userData'), function() {
	// 		model.initDb(app.getPath('userData'));
	// 	// });
	// });
  //
	// describe('Questions', function() {
	// 	describe('getQuestions()', function() {
	// 		it('should return all questions', function() {
	// 			console.log("model", model.getQuestions());
	// 		})
	// 	})
	// })

})
<|endoftext|>